Java (익명 클래스 Anonymous Class)

최병현·2026년 1월 10일

Java

목록 보기
37/38

이번 글에서는 Backend / OOP logic in Java 영역에서 자주 등장하는 익명 클래스(Anonymous Class)를 정리한다. 추상 클래스(Abstract Class)와 함께 사용할 때 어떤 의미를 가지는지, 그리고 “일회성 구현”이 왜 필요한지 구조 중심으로 이해해보자.


1. 개념 정리: 익명 클래스란?

익명 클래스는 “이름 없는 클래스”다. 보통 클래스는 파일로 분리해서 선언하지만, 익명 클래스는 객체를 생성하는 순간 그 자리에서 클래스를 정의한다.

즉, 다음 구조다.

  • 상위 타입(추상 클래스 또는 인터페이스)을 상속/구현
  • 클래스 이름 없이 바로 메서드를 오버라이드
  • 그 객체를 한 번만 사용

핵심 포인트는 이거다.

“한 번만 쓰는 구현체라서, 굳이 클래스 파일을 따로 만들지 않는다.”


2. 구조 비교: 일반 구현 클래스 vs 익명 클래스

먼저 일반적인 방식이다.

  • 추상 클래스 정의
  • 구현 클래스 생성
  • 객체 생성

그 다음, 익명 클래스 방식이다.

  • 추상 클래스 정의
  • 구현 클래스 파일을 만들지 않음
  • 객체 생성 시 바로 오버라이드

둘 다 업캐스팅(부모 타입 참조) 구조를 사용한다는 점이 중요하다.


3. 추상 클래스 구조

먼저 추상 클래스는 “구현 규칙(메서드 시그니처)”만 정의하고, 실제 동작은 하위 클래스에게 맡긴다.

public abstract class AbstractTest {

    public abstract void showData(String data);
    public abstract void add(int num1, int num2);

}

여기서 AbstractTest는 객체를 직접 생성할 수 없고, 반드시 메서드를 구현한 하위 클래스가 필요하다.


4. 일반 구현 클래스 방식

추상 클래스를 상속받아 별도의 구현 클래스를 만든다.

public class AbstractTestImpl extends AbstractTest {

    @Override
    public void showData(String data) {
        System.out.println("data: " + data);
    }

    @Override
    public void add(int num1, int num2) {
        System.out.println("num1: " + num1);
        System.out.println("num2: " + num2);
    }
}

그리고 객체를 생성할 때는 업캐스팅 구조를 사용한다.

AbstractTest abstractTest = new AbstractTestImpl();
abstractTest.showData("gildong");
abstractTest.add(10, 20);

이 방식은 재사용 가능한 구현에 적합하다. 여러 곳에서 같은 로직을 쓰거나, 역할이 명확한 클래스라면 이렇게 분리하는 게 맞다.


5. 익명 클래스 방식

이번에는 구현 클래스를 따로 만들지 않고, 객체 생성과 동시에 구현한다.

AbstractTest abstractTest2 = new AbstractTest() {

    @Override
    public void showData(String data) {
        System.out.println("익명");
        System.out.println("data: " + data);
    }

    @Override
    public void add(int num1, int num2) {
        System.out.println("익명");
        System.out.println("num1: " + num1);
        System.out.println("num2: " + num2);
    }
};

abstractTest2.showData("gilseo");
abstractTest2.add(10, 20);

이 코드의 의미는 다음과 같다.

  • new AbstractTest(): 추상 클래스를 상속하는 새로운 클래스 생성
  • 클래스 이름이 없음 → 익명 클래스
  • 중괄호 안에서 모든 추상 메서드를 즉시 구현
  • 해당 객체는 보통 한 번만 사용

6. 동작 원리(OOP 관점)

두 방식 모두 본질은 동일하다.

부모 타입(AbstractTest) 참조 변수에 자식 객체를 담는 업캐스팅

차이점은 “구현 클래스가 파일로 존재하느냐” vs “실행 시점에 즉석에서 만들어지느냐”이다.

컴파일 시, 익명 클래스도 내부적으로는 다음과 같은 형태로 처리된다.

  • 컴파일러가 내부 클래스를 자동 생성 (예: AbstractTest$1.class)
  • 실행 시에는 일반 클래스와 동일하게 동작

7. 언제 익명 클래스를 쓰는가?

  • 한 번만 사용하는 구현
  • 콜백(callback) 구조
  • 이벤트 처리
  • 테스트용 임시 구현

예를 들어:

  • 버튼 클릭 이벤트
  • 스레드 실행 로직
  • 전략(Strategy)을 상황에 따라 즉석에서 주입

이런 경우, 클래스 파일을 하나 더 만드는 것보다 익명 클래스가 훨씬 간결하다.


8. 주의점

  • 재사용 불가: 클래스 이름이 없으므로 다른 곳에서 다시 쓸 수 없다.
  • 가독성: 로직이 길어지면 코드가 지저분해진다.
  • 디버깅: 이름이 없어서 스택 트레이스에서 추적이 다소 불편할 수 있다.

따라서 기준은 명확하다.

“짧고 일회성 → 익명 클래스”
“여러 곳에서 재사용 → 일반 구현 클래스”


9. 확장: 인터페이스 + 람다와의 관계

익명 클래스는 자바 8 이후 람다(lambda)로 더 간결해질 수 있다. 단, 추상 메서드가 하나뿐인 인터페이스일 때만 람다로 대체 가능하다.

즉:

  • 추상 클래스 → 익명 클래스 사용
  • 함수형 인터페이스 → 람다 사용

이 구분이 실무에서 매우 중요하다.


10. 정리

  • 익명 클래스는 “이름 없는 구현 클래스”
  • 객체 생성 시점에 바로 메서드를 오버라이드
  • 일회성 구현, 콜백, 테스트용 코드에 적합
  • 재사용이 필요하면 일반 클래스 분리

11. 느낀 점

익명 클래스는 단순한 문법이 아니라, “구현을 구조적으로 분리하면서도, 불필요한 클래스 파일 생성을 줄이기 위한 OOP 설계 도구”라는 점이 인상 깊었다. 특히 콜백, 전략 패턴, 이벤트 처리처럼 “동작을 객체로 넘기는 구조”에서 익명 클래스는 코드의 의도를 가장 직관적으로 드러내는 방법이다.

profile
No Pain No Gain

0개의 댓글