Java Anonymous Class

익명 클래스는 지역클래스 중 하나이다.
익명 클래스는 클래스 이름이 없는 것이 특징이다.

예제 코드의 이름 있는 지역 클래스에서 익명 클래스로 변경해보도록 한다.

Printer.class

public interface Printer {
    void print();
}

LocalOuter.class

public class LocalOuter {
    private int OutInstanceVar = 3;

    public void process(int paramVar) {

        int localVar = 1;

        class LocalPrinter implements Printer{
            int value = 0;

            @Override
            public void print() {
                System.out.println("value is " + value);
                System.out.println("localVar is " + localVar);
                System.out.println("paramVar is " + paramVar);
                System.out.println("OutInstanceVar is " + OutInstanceVar);
            }
        }

        LocalPrinter printer = new LocalPrinter();
        printer.print();
    }

    public static void main(String[] args) {
        LocalOuter localOuter = new LocalOuter();
        localOuter.process(2);
    }
}

value is 0
localVar is 1
paramVar is 2
OutInstanceVar is 3

지역 클래스 사용에는 2단계가 있다.

지역 클래스 생성

  1. 선언
    1. LocalPrinter 라는 지역 클래스 이름으로 선언.
    2. 지역클래스 상속 용도로 Printer 인터페이스 구현
  2. 생성
    1. new LocalPrinter() 사용해 지역 클래스의 인스턴스 생성

코드 선언부

class LocalPrinter implements Printer{
    ...
}

코드 생성부

LocalPrinter printer = new LocalPrinter();
...

익명 클래스의 생성

익명 클래스를 사용하면 클래스 이름을 생략하며 클래스 선언과 생성을 한번에 처리할 수 있다.

public class LocalOuter {
    private int OutInstanceVar = 3;

    public void process(int paramVar) {

        int localVar = 1;

        Printer printer = new Printer() {
            int value = 0;

            @Override
            public void print() {
                System.out.println("value is " + value);
                System.out.println("localVar is " + localVar);
                System.out.println("paramVar is " + paramVar);
                System.out.println("OutInstanceVar is " + OutInstanceVar);
            }
        };
        
        printer.print();
        System.out.println("printer.class is " + printer.getClass());
    }

    public static void main(String[] args) {
        LocalOuter localOuter = new LocalOuter();
        localOuter.process(2);
    }
}

value is 0
localVar is 1
paramVar is 2
OutInstanceVar is 3
printer.class is class LocalOuter$1

익명 클래스 이름을 알기 위해 클래스명을 출력하였으나 $1, $2 순차적으로 출력한다.

new Printer() {...} 코드

익명 클래스의 본문(body)과 정의하면서 생성한다.

new 다음 상속 받을 부모 타입을 입력하엿다. 마치 인터페이스 Printer 생성하는 것처럼 보인다.
그렇지만 자바는 인터페이스 생성이 불가능하다. 이 코드는 인터페이스 생성이 아닌 Printer 이름의 인터페이스를 가진 익명 클래스를 생성한 것이다.
{...} 본문에 Printer 인터페이스로 구현 코드를 작성이 익명 클래스의 본문이다.
Printer 상속(구현)하면서 생성한 것이다.

익명 클래스 특징

  • 익명 클래스는 이름 없는 지역 클래스
  • 익명 클래스는 선언과 동시에 생성함
  • 부모 클래스를 상속 또는 인터페이스로 구현이 필요.
    • 상위의 클래스 또는 인터페이스가 필요하다.
  • 익명 클래스는 이름이 없으므로 생성자가 없다. (기본 생성자만 이용)
  • 익명 클래스 자바에서는 $1, $2 특수문자($)와 숫자로 정의하며, 숫자는 익명 클래스 갯수만큼 증가하여 구분함

익명 클래스 사용 이유는?

익명클래스로 별도의 이름을 주어지지 않아도 인터페이스 추상 클래스로 즉성으로 구현되며, 더 간결해진다.
그렇지만 복잡한 코드거나 재사용이 필요한 경우에는 익명 클래스 사용에 지양해야한다.

코드에 익명 클래스 사용할 수 없는 케이스

익명 클래스는 단 하나의 인스턴스만을 생성한다. 여러 인스턴스 생성에는 사용 불가능하다. 이럴 때는 지역 클래스로 선언하고 사용하자.

// 다수의 인스턴스 사용에는 지역 클래스 사용
Printer printer1 = new LocalPrinter(); 
Printer printer2 = new LocalPrinter();

익명 클래스 정리

  • 익명 클래스는 이름이 없음
  • 특정 부모 클래스나 인터페이스 상속 받고 생성에 사용
  • 익명 클래스는 지역 클래스가 일회성이거나 간단한 구현에 사용