익명 클래스는 클래스의 선언과 객체의 생성을 동시에 하는 이름이 없는 클래스를 말한다. 보통 인터페이스나 추상 클래스를 구현할 때 사용된다.
익명 클래스를 사용하면 클래스를 별도로 선언하지 않고도 일회성으로 클래스를 상속받거나 인터페이스를 구현하여 사용할 수 있으므로, 코드를 간결하게 만들 수 있다. 단, 익명 클래스는 재사용이 불가능하기 때문에 반복적으로 사용해야 하는 경우 별도의 클래스를 선언하는 것이 좋다.
new Thread(new Runnable() {
public void run() {
System.out.println("익명 클래스의 예");
}
}).start();
위 코드에서는 파라미터에 전달되는 new Runnable() {…} 부분이 익명 클래스이다. 여기서 Runnable은 인터페이스이며, 이를 구현하는 익명의 클래스가 생성되고 있다.
Java에서 **new Runnable() {...}**과 같은 표현식은 익명 클래스를 정의하고 인스턴스화하는 것을 의미한다. 이 코드의 구조를 더 자세히 살펴보면 다음과 같다.
new Runnable()**는 Runnable 인터페이스의 새로운 인스턴스를 만드는 것을 시도한다. 그러나 **Runnable**은 인터페이스이므로, 그 자체로는 인스턴스를 만들 수 없다.{...} 부분은 이 새 인스턴스의 정의를 제공한다. 이것이 익명 클래스의 본문이며, 이 클래스는 Runnable 인터페이스를 구현한다. 이 클래스는 run 메소드를 재정의하여 해당 메소드가 호출될 때 실행할 코드를 제공한다.;**는 이 전체 표현식을 종료한다. Java에서 각 표현식은 세미콜론으로 끝나야 한다.public class Anonymous {
// 필드 초기값으로 대입
Person field = new Person(){
void work() {
System.out.println("출근합니다.");
}
@Override
void wake() {
System.out.println("6시에 일어납니다.");
work();
}
};
}
위 코드에서는 Person 클래스를 상속받는 익명 클래스를 생성하고 있으며, 이 익명 클래스는 work()라는 새로운 메소드를 추가하고 wake() 메소드를 오버라이드하며 직전에 추가한 work() 메소드를 호출한다.
public class Anonymous {
void method() {
// 로컬 변수값으로 대입
Person localVar = new Person() {
void walk() {
System.out.println("산책합니다.");
}
@Override
void wake() {
System.out.println("7시에 일어납니다.");
walk();
}
};
//로컬 변수 사용
localVar.wake();
}
}
위 코드에서도 Person 클래스를 상속받는 익명 클래스를 생성하고 있으며, 필드 초기값에 대입하는 것과 같은 방식으로 작성할 수 있다.
public class Anonymous {
void method(Person person) {
person.wake();
}
}
public class AnonymousExample {
public static void main(String[] args) {
Anonymous anony = new Anonymous();
anony.method(
new Person() {
void study() {
System.out.println("공부합니다.");
}
@Override
void wake() {
System.out.println("8시에 일어납니다.");
study();
}
}
);
}
}
위 코드는 메소드의 파라미터인 Person타입의 인자값을 전달해주는 과정에서 익명 클래스를 생성하며 그 인스턴스를 넘겨주는 것이다. 이는 메소드를 호출할 때 가능하다.