익명 클래스
탄생 배경
추상 클래스와 인터페이스는 객체를 생성하려고 하면 에러가 발생하게 된다.
- 메소드의 구현체가 존재하지 않기 때문이다.
- 사실 default method는 자바 8 이후로 구현체를 인터페이스에 작성할 수 있게 됐다.
- 하지만 통일성을 위해 이 규칙은 유지
- default method를 구현해도 여전히 객체를 생성할 수 없다

익명 객체
익명 클래스는 이름 없는 일회성 클래스를 정의하며, 추상 클래스나 인터페이스를 상속(또는 구현) 하여 필요한 메서드를 즉시 재정의한 뒤 인스턴스를 생성한다.
abstract class A {
abstract int method(int a, int b);
}
abstract class B {
int method(int a, int b) {
return a - b;
}
}
interface I {
int method(int a, int b);
}
public class Main {
public static void main(String[] args) {
A a = new A() {
@Override
int method(int a, int b) {
return a + b;
}
};
System.out.println(a.method(10, 2));
//이미 작성된 메소드로 오버라이딩이 가능하다.
B b = new B() {
@Override
int method(int a, int b) {
return a / b;
}
};
System.out.println(b.method(10, 2));
I i = new I() {
@Override
public int method(int a, int b) {
return a * b;
}
};
System.out.println(i.method(10, 2));
}
}
- 헷갈릴 수 있는 부분
익명 클래스를 사용하면 인터페이스나 추상 클래스를 객체로 만들 수 있구나!! (X)
추상클래스, 또는 인터페이스를 "상속 받는 객체"를 만들어주는 것이 핵심
A a = new A() { @Override ~~~} → A를 상속 받는 클래스를 인스턴스화 + 내부 클래스로 정의
코드를 통해 보자
abstract class A {
abstract int method(int a, int b);
}
abstract class B {
abstract int method(int a, int b);
}
public class Main {
public static void main(String[] args) {
A a1 = new A() {
@Override
int method(int a, int b) {
return a - b;
}
};
A a2 = new A() {
@Override
int method(int a, int b) {
return a - b;
}
};
B b = new B() {
@Override
int method(int a, int b) {
return a * b;
}
};
System.out.println("A.getClass() == "+ A.class);
System.out.println("a1.getClass() == "+ a1.getClass());
System.out.println("a1.getClass() == "+ a2.getClass());
System.out.println("b.getClass() == "+ b.getClass());
}
}
출력 결과

컴파일러가 자동으로 Main 클래스 안에 중첩(Nested)된 이름 없는 클래스로 생성
→ 부모 클래스의 하위로 가는게 아닌 Nested Class로 선언되는게 포인트
컴파일러 동작 예시
//실제로는 클래스가 다르지만 이해하기 편하게 이런식이라고 생각하면 됩니다
public class Main {
public static void main(String[] args) {
class Main$1 extends A {
@Override
int method(int a, int b) {
return a - b;
}
}
class Main$2 extends A {
@Override
int method(int a, int b) {
return a - b;
}
}
class Main$3 extends B {
@Override
int method(int a, int b) {
return a * b;
}
}
}
}
사용예시)
- 익명 클래스 사용 안할 시
import java.util.Comparator;
import java.util.PriorityQueue;
//Comparator 구현
class AscendingComparator implements Comparator<Integer> {
@Override
public int compare(Integer o1, Integer o2) {
return o1 - o2;
}
}
public class NamedClassExample {
public static void main(String[] args) {
// 명시적 클래스의 인스턴스 생성 후 전달
PriorityQueue<Integer> q = new PriorityQueue<>(new AscendingComparator());
}
}
- 익명 클래스 사용 시
PriorityQueue<Integer> q = new PriorityQueue<>(new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o1 - o
}
});
장단점
- 장점 : 익명 클래스를 사용하면 지역 클래스의 선언과 생성을 한 번에 할 수 있다는 점에서 코드가 간결해진다.
- 단점 : 복잡하거나 재사용이 필요한 경우에는 별도의 클래스를 정의
- override 해야 할 메소드가 많거나 코드가 복잡하면 가독성이 떨어진다
- 해당 override를 재사용 할 수 없기 때문에 재사용이 불가능
'JAVA' 카테고리의 다른 글
| [Java] 클래스는 왜 하나만 상속 받을 수 있을까? (1) | 2025.05.04 |
|---|---|
| [문법] int 배열의 stream (1) | 2024.06.10 |
| [JAVA] Steam의 특징과 컬랙션과 차이 (0) | 2024.03.12 |