본문으로 바로가기

1. 익명 객체

  • 이름이 없는 객체
  • 익명 객체는 단독으로 생성할 수 없고 클래스를 상속하거나 인터페이스를 구현해야만 생성할 수 있습니다.
  • 익명 객체는 필드의 초기값이나 로컬 변수의 초기값, 매개 변수의 매개 값으로 주로 대입
  • UI 이벤트 처리 객체나 스레드 객체를 간편하게 생성할 목적으로 익명 객체가 많이 활용

 

2. 익명 자식 객체 (extends)

일반적인 상속을 이용한 객체 사용법

public class Parent {
    String name = "Parent Class";

    void methodParent() {
        System.out.println("class name(Parent): " + this.name);
    }
}
public class Child extends Parent {
    String name = "Child Class";

    @Override
    void methodParent() {
        System.out.println("class name(Child): " + this.name);
        System.out.println("class name(Parent): " + super.name);
    }
}
Parent parent = new Child();
parent.methodParent();

 

자식 객체가 일회성이라면?

다형성을 위해 부모 타입으로 필드나 변수를 선언하고, 자식 객체를 초기값으로 대입하는 경우

자식 클래스가 재사용되지 않고, 오로지 해당 필드와 변수의 초기값으로만 사용할 경우라면 (일회용)

익명 자식 객체를 생성해서 초기값으로 대입하는 것을 권장합니다.

 

익명 자식 객체 생성

  • 일반 클래스와의 차이점은 익명 자식 객체는 생성자를 선언할 수 없습니다.
  • 익명 자식 객체에 새롭게 정의된 필드와 메소드는 익명 자식 객체 내부에서만 사용되고, 외부에서는 필드와 메소드에 접근할 수 없습니다. (타입이 부모 타입이기 때문입니다.)
부모클래스 [필드|변수] = new 부모클래스(매개값, ...) {
	// 필드
	// 메소드
	// 생성자는 가질 수 없습니다.
};

 

예시

부모 클래스 CPU

public class CPU {
    private String modelName;
    private int coreCnt;

    public CPU(String modelName, int coreCnt) {
        this.modelName = modelName;
        this.coreCnt = coreCnt;
    }

    public String getModelName() {
        return modelName;
    }

    public int getCoreCnt() {
        return coreCnt;
    }

    public void cpuSpec() {
        System.out.println(this.coreCnt);
        System.out.println(this.modelName);
    }
}

 

CPU 클래스를 활용하는 Computer 클래스

public class Computer {
    // 필드
    CPU fieldCpu = new CPU("intel-001", 8) {
        @Override
        public void cpuSpec() {
            System.out.println("---- Intel CPU STATUS ----");
            System.out.println("모델명: " + getModelName());
            System.out.println("코어 수: " + getCoreCnt());
            System.out.println("---- Intel CPU STATUS ----" + '\n');
        }
    };

    // 로컬 변수
    void methodA() {
        CPU localCpu = new CPU("amd-001", 4) {
            @Override
            public void cpuSpec() {
                System.out.println("---- AMD CPU STATUS ----");
                System.out.println("모델명: " + getModelName());
                System.out.println("코어 수: " + getCoreCnt());
                System.out.println("---- AMD CPU STATUS ----" + '\n');
            }
        };
        localCpu.cpuSpec();
    }
    
    // 매개 변수
    void methodB(CPU cpu) {
        cpu.cpuSpec();
    }
}

 

실행

Computer computer = new Computer();

computer.fieldCpu.cpuSpec(); // 필드
computer.methodA(); // 메소드(로컬 변수)

CPU IntelCpu = new CPU("intel-003", 16) {
    @Override
    public void cpuSpec() {
        System.out.println("---- Intel CPU STATUS ----");
        System.out.println("모델명: " + getModelName());
        System.out.println("코어 수: " + getCoreCnt());
        System.out.println("---- Intel CPU STATUS ----" + '\n');
    }
};

computer.methodB(IntelCpu); // 메소드(매개 변수)

 

3. 익명 구현 객체 (implements)

인터페이스 타입으로 필드나 변수를 선언하고, 구현 객체를 초기값으로 대입하는 경우

구현 클래스가 재사용되지 않고, 오로지 해당 필드와 변수의 초기값으로만 사용하는 경우라면 (일회용)

익명 구현 객체를 초기값으로 대입하는 것이 좋습니다.

 

익명 구현 객체 생성

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

 

예시

인터페이스 OnEvent

public interface OnEvent {
    void on();
}

 

OnEvent 인터페이스를 활용하는 MacBook 클래스

public class MacBook {
    // 필드
    OnEvent fieldOnEvent = new OnEvent() {
        @Override
        public void on() {
            System.out.println("Mac Book ON(Field)");
        }
    };

    // 로컬 변수
    void methodA() {
        OnEvent localOnEvent = new OnEvent() {
            @Override
            public void on() {
                System.out.println("Mac Book ON(Local Variable)");
            }
        };
        localOnEvent.on();
    }

    // 매개 변수
    void methodB(OnEvent onEvent) {
        onEvent.on();
    }
}

 

실행

MacBook macBook = new MacBook();

macBook.fieldOnEvent.on(); // 필드
macBook.methodA(); // 로컬 변수

// 매개 변수
macBook.methodB(new OnEvent() {
    @Override
    public void on() {
        System.out.println("Mac Book ON(Parameter)");
    }
});

// 인터페이스가 추상 메소드가 1개인 함수적 인터페이스라면 람다를 활용할 수도 있습니다.
macBook.methodB(() -> System.out.println("Mac Book ON(Parameter & Lambda)"));

 

※ 람다식은 런타임 시에는 익명 구현 객체를 생성합니다.

 람다식은 인터페이스 변수에 대입됩니다.