
익명 클래스는 일회성으로 클래스를 정의하고 바로 객체를 생성할 수 있는 강력한 기능이다. 익명 클래스를 잘 활용하면 코드의 길이를 줄이고, 특정 로직을 간단히 처리할 수 있다. 하지만 이러한 익명 클래스를 사용할 때 꼭 알아야 할 점이 있다.
익명 클래스는 이름이 없는 클래스이다. 이를 통해 다음과 같은 특징을 가진다.
익명 클래스는 반드시 상속하거나 인터페이스를 구현해야만 사용할 수 있다. 즉, 기존 클래스를 확장하거나, 인터페이스를 구현하는 일회용 객체를 만들 때 사용된다.
💡 익명 클래스는 기존에 정의한 클래스나 인터페이스를 재정의하여 한 번만 사용할 객체를 만드는 기법이다.
abstract class Animal {
abstract void sound();
}
Animal dog = new Animal() {
@Override
void sound() {
System.out.println("멍멍");
}
};
interface ClickListener {
void onClick();
}
ClickListener listener = new ClickListener() {
@Override
public void onClick() {
System.out.println("클릭됨");
}
};
💡 익명 클래스는 새로운 클래스를 정의하는 것이 아니라, 이미 정의된 클래스의 멤버를 일회성으로 재정의하여 사용하는 기법이다. 즉, 부모 클래스의 자원을 한 번만 재정의해서 사용하는 용도이다.
익명 클래스는 하나의 인터페이스만 구현할 수 있다. 여러 인터페이스를 동시에 상속하거나 구현하려면, 명시적인 클래스를 선언해야 한다.
interface IAnimal {
void sound();
}
interface ICreature {
void move();
}
// ❌ 익명 클래스에서는 두 인터페이스를 동시에 구현할 수 없다
IAnimal creature = new IAnimal, ICreature() {
@Override
public void sound() {
System.out.println("동물 소리");
}
@Override
public void move() {
System.out.println("이동");
}
};
abstract class MyClass {
abstract void print();
}
interface IAnimal {
void sound();
}
// ❌ 익명 클래스에서는 클래스를 상속하고 인터페이스를 동시에 구현할 수 없다
MyClass myObject = new MyClass() implements IAnimal {
@Override
public void sound() {
System.out.println("소리");
}
@Override
void print() {
System.out.println("프린트");
}
};
기존의 자식 클래스에서는 부모 메서드를 오버라이딩하고 새로운 메서드를 추가할 수 있지만, 익명 클래스에서는 오버라이딩한 메서드만 사용 가능하고, 새로 정의한 메서드는 외부에서 호출할 수 없다.
// 부모 클래스
class Animal {
public String bark() {
return "동물이 웁니다";
}
}
public class Main {
public static void main(String[] args) {
Animal dog = new Animal() {
// @Override 메소드
public String bark() {
return "개가 짖습니다";
}
// 새로 정의한 메소드
public String run() {
return "달리기 ㄱㄱ싱";
}
};
dog.bark();
dog.run(); // ! Error - 외부에서 호출 불가능
}
}
익명 클래스는 Animal 클래스를 상속받은 익명 자식 클래스이므로, run() 메서드는 Animal 클래스에 정의되지 않아 외부에서 호출할 수 없다. 즉, 다형성에 의해 Animal 타입 변수에서는 부모 클래스에서 정의된 메서드만 호출 가능하다.
자바 8부터 람다 표현식이 도입되면서, 익명 클래스는 더 간결하게 표현할 수 있게 되었다. 특히, 인터페이스 구현에서 람다 표현식은 익명 클래스보다 더욱 간결하고, 간단한 이벤트 처리나 콜백 함수를 작성할 때 유용하다.
람다식 표현 예시
Runnable r = () -> System.out.println("실행 중!");
익명 클래스는 단발성 로직을 간결하게 처리할 수 있는 유용한 도구이다. 주로 이벤트 처리나 콜백 함수에 적합하며, 상속이나 인터페이스 구현을 통해 빠르게 객체를 생성할 수 있다. 하지만 새로운 메서드 정의나 다중 인터페이스 구현에는 제한이 있어 복잡한 구조에는 불편할 수 있다.
추후에는 람다식과 익명 클래스의 차이점과, 각각 어떤 상황에서 더 적합한지에 대해 살펴보겠습니다.