익명객체
이름이 없는 객체
익명객체를 만드는 조건은
어떤 클래스를 상속하거나
인터페이스를 구현하는 경우
일반적인 경우
상속 | (인터페이스)구현 |
class 자식 extends 부모클래스{...} 부모클래스 변수 = new 자식(); |
class 구현클래스 implements 인터페이스{...} 인터페이스 변수 = new 구현클래스(); |
익명객체를 사용할 경우
상속 | (인터페이스)구현 |
부모클래스 변수 = new 부모클래스(){...}; | 인터페이스 변수 = new 인터페이스(){...}; |
상속
Test클래스 안에서 A의 자식객체로 익명객체를 생성하는 경우
A
public class A{
int fieldA;
void methodA(){
System.out.println("A");
}
}
C(일반적인 자식 클래스)
public class C extends A{
int fieldC;
void methodC(){}
@Override
void methodA(){
System.out.println("C");
}
}
Test(필드값에 익명객체를 대입할 때)
public class Test{
A a = new A(){
@Override
void methodA(){
System.out.println("B");//부모 클래스인 A의 메소드 재정의
}
};//익명객체 생성
A b = new C();//일반적으로 부모클래스에 자식객체 대입할 때
}
Test(메소드 내에서 로컬 변수에 익명객체를 대입할 때)
public class Test{
void testMethod(){
A a =new A(){
@Override
void methodA(){
System.out.println("B");//부모 클래스인 A의 메소드 재정의
}
};//익명객체 생성
}
void testMethod2(){
A a = new C();//일반적으로 부모클래스에 자식객체 대입할 때
}
}
Test(메소드의 매개변수가 부모 타입일 경우 메소드 매개변수로 자식타입인 익명객체를 대입하는경우)
public class Test{
void method1(A a){}//부모 클래스를 매개변수로 받는 메소드
void method2(){
method1(
new A(){//메소드에 매개변수로 들어가는 자식 익명객체
@Override
void methodA(){
System.out.println("B");//부모 클래스의 메소드를 재정의
}
}//익명객체 생성
);
}
void method3(){
method1(new C());//일반적으로 매소드 매개변수에 자식클래스를 줄때
}
}
주의할 점
Test
public class Test{
A a = new A(){//필드1 자식 타입인 익명객체 대입
int fieldB;
void methodB(){}//익명객체의 새로운 메소드
@Override
void methodA(){//익명객체에서 재정의하는 부모 클래스의 메소드
System.out.println("B");
fieldB = 10;
methodB();
}
};
A ac = new C();//필드2 자식 타입의 객체 대입
void methodTest1(){
//a.fieldB=10; ERROR
//a.methodB(); ERROR
//a는 현재 부모 타입이기 때문에 자식인 익명객체의 필드나 메소드를 사용할 수 없음
a.methodA();//이렇게 부모클래스가 가진 필드나 메소드는 사용 가능
a.fieldA=10;
}
void methodTest2(){
//ac.fieldC=10; ERROR
//ac.methodC(); ERROR
ac.methodA();
ac.fieldA=10;
}
//일반적으로 상속받은 자식클래스의 객체를 대입한 부모 타입의 객체도 원래 안됨
C c = new C();
void methodTest3(){
c.fieldC = 10;
c.methodC();
}//이렇게 원래 자식 타입이면 자식클래스의 필드와 메소드 접근가능
}
예제)
Person
public class Person{
void wakeUp(){
System.out.println("7시에 일어납니다.");
}
}
Anonymous
public class Anonymous{
Person field = new Person(){//필드 초기값에 대입
void work(){
System.out.println("출근합니다.");
}
@Override
void wakeUp(){
System.out.println("6시에 일어납니다.");
work();
}
};
void method1(){//로컬 변수에 대입
Person localVal = new Person(){
void walk(){
System.out.println("산책합니다.");
}
@Override
void wakeUp(){
System.out.println("7시에 일어납니다.");
walk();
}
};
localVal.wakeUp();
}
void method2(Person person){
person.wakeUp();
}
}
AnonymousTest
public class AnonymousTest{
public static void main(String[] args){
Anonymous anony = new Anonymous();
anony.field.wakeUp();//익명 객체 필드 사용
anony.method1();//익명 객체 로컬 변수 사용
anony.method2(//익명 객체 매개값으로 사용
new Person(){
void study(){
System.out.println("공부합니다.");
}
@Override
void wakeUp(){
System.out.println("8시에 일어납니다.");
study();
}
}
);
}
}
익명 구현 객체(인터페이스)
A(인터페이스)
public interface A{
void methodA();
}
C(일반적인 구현 클래스)
public class C implements A{
@Override
public void methodA(){}//인터페이스의 추상메소드의 실체메소드 선언
}
Test(필드값에 익명 구현 객체 대입)
public class Test{
A a = new A(){//익명 구현 객체 대입
@Override
public void methodA(){}
};
A ac = new C();//일반적인 인터페이스 타입에 구현 객체 대입
}
Test(로컬 변수에 익명 구현 객체 대입)
public class Test{
void testMethod1(){
A a = new A(){//로컬 변수에 익명 구현 객체 대입
@Override
public void methodA(){};
};
}
void testMethod2(){
A a = new C();//일반적인 로컬변수에 구현 객체 대입
}
}
Test(메소드의 매개변수가 인터페이스 타입일 때 익명 구현 객체 대입)
public class Test{
void testMethod1(A a){}
void testMethod2(){
testMethod1(//매개변수로 익명 구현 객체 대입
new A(){
@Override
public void methodA(){}
}
);
testMethod1(new C());//일반적인 인터페이스 타입 매개변수에 구현 객체 대입
}
}