Notice
Recent Posts
Recent Comments
Link
«   2025/04   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30
Archives
Today
Total
관리 메뉴

나는개발자니까

[Java] Chapter 9.2 익명 객체 본문

Java

[Java] Chapter 9.2 익명 객체

된다고했잖아요 2023. 5. 3. 20:58

 

 

익명 객체의 개요

익명 객체는 이름이 없는 객체입니다.  익명 객체를 사용하기 위한 조건은 어떤 클래스를 상속하거나 인터페이스를 구현해야 사용할 수 있습니다.  익명 객체를 사용하면 부모 클래스 변수는 이름이 없는 자식 객체를 참조하고, 인터페이스 변수는 이름이 없는 구현 객체를 참조합니다.  

 

1. [상속]
부모클래스 변수 = new 부모클래스() {
	// ...
};
2. [구현]
인터페이스 변수 = new 인터페이스() {
	// ...
};



익명 자식 객체 생성

익명 자식 객체를 생성하는 방법은 아래와 같습니다.

 부모클래스 [필드|변수] = new 부모클래스(매개값, ---) {
 	// 필드
    // 메소드
};

 

자식 클래스가 재사용되지 않고, 특정 위치에서 사용할 경우라면 자식 클래스를 명시적으로 선언하는 것보다는 익명 자식 객체를 생성하는 것이 좋습니다.

 

부모 클래스(매개값, ...) { ...}

부모 클래스를 상속해서 중괄호 {} 와 같이 자식 클래스를 선언합니다.  new 연산자는 선언된 자식 클래스를 객체로 생성합니다.

 

부모 클래스(매개값, ...)

부모 생성자를 호출하는 코드입니다.  매개값은 부모 생성자의 매개 변수에 맞게 입력합니다.

중괄호 {} 내부에는 필드나 메소드를 선언하거나 부모 클래스의 메소드를 재정의할 내용을 작성합니다.  일반 클래스와 다르게 생성자를 선언할 수 없습니다.

 

익명 자식 객체를 생성하는 방법에는 3가지가 있습니다.

 

1. 필드를 선언할 때 초기값으로 익명 자식 객체를 생성해서 대입합니다.

class A {
	// A 클래스의 필드 선언
	Parent field = new Parent() {
    	int childField;
        void childMethod() { }
        // Parent의 메소드를 재정의
        @Override
        void parentMethod() { }
    };
}

 

2. 메소드 내에서 로컬 변수를 선언할 때 초기값으로 익명 자식 객체를 생성해서 대입합니다.

class A {
	void method() {
    	Parent localVar = new Parent() {
        	int childField;
            void childMethod() { }
            @Override
            void parentMethod() { }
        };
    }
}

 

3. 메소드의 매개 변수가 부모 타입일 경우 메소드를 호출하는 코드에서 익명 자식 객체를 생성해서 매개값으로 대입합니다.

class A {
	void method1(Parent parent) { }
    
    void method2() {
    	// method1() 메소드 호출
    	method1(
        // method1()의 매개값으로 익명 자식 객체를 대입
        	new Parent() {
            	int childField;
                void childMethod() { }
                @Override
                void parentMethod() { }
            }
       };
    }
}

 

익명 자식 객체에 새롭게 정의된 필드와 메소드는 익명 자식 객체 내부에서만 사용되고, 외부에서는 접근할 수 없습니다.  익명 자식 객체는 부모 타입 변수에 대입되므로 부모 타입에 선언된 것만 사용할 수 있기 때문이다.

 

 

익명 구현 객체 생성

익명 구현 객체를 생성하는 방법은 다음과 같습니다.

인터페이스 [필드|변수] = new 인터페이스() {
	// 인터페이스에 선언된 추상 메소드의 실체 메소드 선언
    // 필드
    // 메소드
}

 

구현 클래스가 재사용되지 않고, 특정 위치에서 사용할 경우라면 구현 클래스를 명시적으로 선언하는 것보다는 익명 구현 객체를 생성하는 것이 좋습니다.

 

인터페이스() { ... }

인터페이스를 구현해서 중괄호 {}와 같이 클래스를 선언합니다.  new 연산자는 선언된 구현 클래스를 객체로 생성합니다.  중괄호 {}에는 인터페이스에 선언된 모든 추상 메소드의 실체 메소드를 재정의해야 합니다.

 

익명 구현 객체를 생성하는 방법에는 3가지가 있습니다.

 

1. 필드를 선언할 때 초기값으로 익명 구현 객체를 생성해서 대입합니다.

class A {
	// 클래스 A의 필드 선언
	RemoteControl field = new RemoteControl() {
    	// RemoteControl 인터페이스의 추상 메소드에 대한 실체 메소드
    	@Override
        void turnOn() { }
    };
}

 

2. 메소드 내에서 로컬 변수를 선언할 때 초기값으로 익명 구현 객체를 생성해서 대입합니다. 

void method() {
	// 로컬 변수 선언
	RemoteControl localVar = new RemoteControl() {
    	// RemoteControl 인터페이스의 추상 메소드에 대한 실체 메소드
    	@Override
        void turnOn() { }
    };
}


3. 메소드의 매개 변수가 인터페이스 타입일 경우 메소드를 호출하는 코드에서 익명 구현 객체를 생성해서 매개값으로 대입합니다.

class A {
	void method1(RemoteControl rc) { }
    
    void method2() {
    	// method1() 메소드 호출
    	method1(
        	// method1()의 매개값으로 익명 구현 객체를 대입
        	new RemoteControl() {
            	@Override
                void turnOn() { }
            }
        );
    }
}

 

익명 객체의 로컬 변수 사용

메소드의 매개 변수나 로컬 변수를 익명 객체 내부에서 사용할 때 제한이 있습니다.  익명 객체는 메소드 실행이 종료되면 없어지는 것이 일반적이지만, 메소드가 종료되어도 계속 실행 상태로 존재할 수 있습니다.

메소드의 매개 변수나 로컬 변수를 익명 객체 내부에서 사용했을 때 문제가 발생합니다.  매개 변수나 로컬 변수는 메소드 실행이 끝나면 스택 메모리에서 사라지기 때문에 익명 객체에서 지속적으로 사용할 수 없습니다.

 

이 문제를 해결하기 위해 컴파일 시 익명 객체에서 사용하는 매개 변수나 로컬 변수의 값을 익명 객체 내부에 복사해두고 사용합니다.  따라서 매개 변수나 로컬 변수가 수정되어 값이 변경되면 익명 객체에 복사해 둔 값과 달라지므로 매개 변수나 로컬 변수에는 final를 선언해야합니다.

 

* 자바 7 버전 이후로는 매개 변수와 로컬 변수에 final 키워드가 자동으로 부여됩니다. 

 

출처 | 혼자 공부하는 자바