본문 바로가기

프로그래밍/Java

익명객체

익명객체

이름이 없는 객체

 

익명객체를 만드는 조건은

어떤 클래스를 상속하거나

인터페이스를 구현하는 경우

 

일반적인 경우

상속 (인터페이스)구현

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());//일반적인 인터페이스 타입 매개변수에 구현 객체 대입
    }
}

'프로그래밍 > Java' 카테고리의 다른 글

예외 처리  (0) 2019.12.07
예외 클래스  (0) 2019.12.07
중첩 클래스와 중첩 인터페이스  (0) 2019.12.05
인터페이스  (0) 2019.12.04
추상 클래스  (0) 2019.12.04