나는개발자니까
[Java] Chapter 9.2 익명 객체 본문
익명 객체의 개요
익명 객체는 이름이 없는 객체입니다. 익명 객체를 사용하기 위한 조건은 어떤 클래스를 상속하거나 인터페이스를 구현해야 사용할 수 있습니다. 익명 객체를 사용하면 부모 클래스 변수는 이름이 없는 자식 객체를 참조하고, 인터페이스 변수는 이름이 없는 구현 객체를 참조합니다.
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 키워드가 자동으로 부여됩니다.
출처 | 혼자 공부하는 자바
'Java' 카테고리의 다른 글
[Java] Chapter 10.2 예외 처리 (0) | 2023.05.10 |
---|---|
[Java] Chapter 10.1 예외 클래스 (0) | 2023.05.10 |
[Java] Chapter 9.1 중첩 클래스와 중첩 인터페이스 소개 (0) | 2023.04.24 |
[Java] Chapter 8.2 인터페이스의 타입 변환과 다형성 (0) | 2023.04.24 |
[Java] Chapter 8.1 인터페이스 (0) | 2023.04.17 |