익명객체의 개념과 특징
- 클래스 이름이 없는 객체
- 클래스 선언과 객체의 생성을 동시에 하기 때문에 단 한번 사용될 수 있고 오직 하나의 객체만을 생성할 수 있는 일회성 클래스
- 이름이 없기때문에 생성자도 가질 수 없다.
- 익명 객체를 만들기 위해서는 어떤 클래스를 상속하거나 인터페이스를 구현
- 부모클래스의 이름이나 구현하고자 하는 인터페이스의 이름을 사용해서 정의하므로 한번에 하나의 클래스로 상속받는 동시에 인터페이스를 구현함
- 단 하나의 클래스를 상속받거나 단 하나의 인터페이스만을 구현할 수 있음
익명객체 문법
new 슈퍼클래스이름() {
// 멤버 선언
};
또는
new 구현인터페이스이름() {
// 멤버 선언
};
익명객체를 사용하지 않는 일반적인 상속 관계
class NormalParent {
public void wake() {
System.out.println("7시 기상!");
}
}
NormalParent 클래스를 상속받는 NormalChild 클래스 정의
class Normalchild extends NormalParent {
public void work() {
System.out.println("출근!");
}
오버라이딩
@Override
public void wake() {
System.out.println("6시 기상!");
work();
}
NormalParent np = new Normalchild();
np.wake(); // 오버라이딩 된 NormalChild의 wake() 메서드 호출
// ~~np.work(); // 참조영역의 축소로 인해 접근 불가~~
}
6시 기상! 출근!
익명 객체를 사용하지 않은 인터페이스 구현 관계
interface NormalInterface {
void run(); // public abstract 생략됨
}
NormalParent 인터페이스를 구현하는 NormalChild2 클래스 정의
class NormalChild2 implements NormalInterface {
@Override
public void run() {
System.out.println("출근 전 러닝하기");
}
}
NormalInterface ni = new NormalChild2();
ni.run();
출근 전 러닝하기
NormalParent를 상속받는 동시에 NormalInterface를 구현하는 NormalChild3 클래스 정의
class NormalChild3 extends NormalParent implements NormalInterface {
public void work() {
System.out.println("출근!");
}
@Override
public void run() {
System.out.println("출근 전 러닝하기");
}
@Override
public void wake() {
System.out.println("5시 기상!");
}
}
NormalParent np2 = new NormalChild3();
np2.wake();
np2.wake();
// => 일반적인 경우 상속과 구현을 동시에 할 수 잇으나
// 업캐스팅을 통해 접근하면 모든 메서드를 사용할 수는 없음
NormalChild3 nc3 = new NormalChild3();
nc3.wake();
nc3.work();
상속관계에 있는 서브클래스를 활용하는 클래스 정의
class UseExtendsClass {
NormalParent p = new Normalchild();
public void method() {
NormalParent localP = new Normalchild(); //로컬변수에 서브클래스 객체를 대입
}
}
- 서브클래스를 명시적으로 선언하여 이미 선언된 서브클래스로 간단히 객체를 생성하여 사용할 수 있음
- 재사용성이 높음
- 그러나, 서브클래스가 재사용되지 않고, 특정 위치에서 사용할 경우라면 서브클래스를 명시적으로 선언하는 것은 귀찮은 작업이 되며 이럴 경우, [익명 자식 객체]를 생성
익명 자식 객체 생성 방법
부모클래스 [필드|변수] = new 부모클래스(매개값,...) {
// 필드(멤버변수)
// 메서드
};
익명 객체를 사용한 클래스 정의
(멤버변수 p를 선언할 때 초기값으로 익명 클래스 사용)
class UseAnonyClass {
NormalParent p = new NormalParent() {
int childVar = 10;
public void childMethod() {
System.out.println("익명 객체에서 정의된 메서드!");
}
@Override
public void wake() {
System.out.println("부모클래스로부터 오버라이딩 된 메서드!");
}
};
public void method() {
// ~~p.childVar = 20; // 접근 불가!
// p.childMethod(); // 접근 불가!~~
p.wake();
}
- 익명자식 객체에 새롭게 정의된 필드(멤버변수)와 메서드는 익명자식 객체 내부에서만 사용 가능, 외부에서는 접근할 수 없음
- 익명자식 객체는 부모 타입 변수에 대입되므로 부모타입에 선언된 것만 사용 가능
익명 객체를 사용한 클래스 정의
멤버 메서드 내에서 로컬변수(localP)를 선언할 때 초기값으로 익명 클래스 사용
class UseAnonyClass2 {
public void method() {
NormalParent localP = new NormalParent() {
int childVar = 10;
public void childMethod() {
System.out.println("익명 객체에서 정의된 메서드!");
}
@Override
public void wake() {
System.out.println("로컬변수 localP에 선언된 익명 객체의 오버라이딩 된 wake() 메서드!");
}
};
localP.wake();
// => 로컬변수는 메서드가 종료되면 stack 메모리 영역에서 삭제
// 따라서, 익명 객체가 저장된 localP는 메서드가 종료되기 전에 사용해야함
}// method()
UseAnonyClass2 uac2 = new UseAnonyClass2();
uac2.method();
익명 객체를 사용한 클래스 정의
메서드의 매개변수가 부모타입일 경우 메서드를 호출하는 코드에서 익명 자식 객체를 생성해 매개값으로 대입
class UseAnonyClass3 {
public void method1(NormalParent parent) {}
public void method2() {
method1(new NormalParent() {
int childVar;
void childMethod() {}
@Override
public void wake() {
System.out.println("매개변수로 사용된 익명 객체의 오버라이딩 된 wake() 메서드!");
}
});
}
public void method3(NormalParent parent) {
parent.wake();
}
}
UseAnonyClass3 uac3 = new UseAnonyClass3();
uac3.method1(np);
uac3.method2();
uac3.method3(new NormalParent() {
public void study() {
System.out.println("공부!");
}
@Override
public void wake() {
System.out.println("4시 기상!");
study();
}
});
// => 매개변수 값으로 익명 객체 대입
예제
Worker 클래스의 익명자식 객체를 이용하여 필드(멤버변수), 로컬변수의 초기값과 메서드의 매개값을 대입
- 필드 : "디자인을 합니다"출력(member)
- 로컬변수 : "개발을 합니다!" 출력(method1)
- 매개값 : "테스트를 합니다!" 출력(method2)
📌Worker 클래스에는 start() 메서드가 정의됨 익명 객체를 이용하는 AnonyClass 정의
package anonymous;
public class Test {
public static void main(String[] args) {
AnonyClass ac = new AnonyClass();
ac.member.start();
ac.method1();
ac.method2(new Worker() {
@Override
public void start() {
System.out.println("테스트를 합니다");
super.start();
}
});
}
}
// 부모 클래스로 사용될 Worker 클래스 정의
class Worker {
public void start() {
System.out.println("쉬고 있습니다");
}
}
// 익명 객체를 이용하는 AnonyClass 정의
class AnonyClass {
// 디자인을 합니다 출력
Worker member = new Worker() {
@Override
public void start() {
System.out.println("디자인을 합니다");
}
};
// 개발을 합니다 출력
public void method1() {
Worker localVar = new Worker() {
@Override
public void start() {
System.out.println("개발을 합니다");
}
};
localVar.start();
}
// 테스트를 합니다 출력
public void method2(Worker worker) {
worker.start();
}
}
'JAVA' 카테고리의 다른 글
[JAVA] 익명(anonymous) 객체 (3) (0) | 2023.11.14 |
---|---|
[JAVA] 익명(anonymous) 객체 (2) (0) | 2023.11.14 |
[JAVA] 제네릭(Generic, 일반화) - 2 (1) | 2023.10.31 |
[JAVA] 제네릭(Generic, 일반화) - 1 (0) | 2023.10.31 |
[JAVA] enum type (2) (0) | 2023.10.31 |