
자바(Java) 프로그래밍을 하다 보면 단 한 번만 사용하고 버려질 클래스를 정의해야 할 때가 있습니다. 이때 별도의 소스 파일(.java)을 만들거나 클래스 이름을 명명하는 것은 코드의 복잡성을 높이고 생산성을 떨어뜨리는 원인이 됩니다. 이러한 불편함을 해결하기 위해 등장한 개념이 바로 익명 클래스(Anonymous Class)입니다. 오늘 포스팅에서는 익명 클래스의 기본 개념부터 내부 동작 원리, 그리고 최신 자바 트렌드인 람다(Lambda)와의 관계까지 전문가의 시각에서 심도 있게 다루어 보겠습니다.
1. 익명 클래스(Anonymous Class)의 정의
익명 클래스는 말 그대로 "이름이 없는 클래스"를 의미합니다. 클래스의 선언과 객체의 생성이 동시에 이루어지는 것이 특징이며, 주로 인터페이스나 추상 클래스의 미구현 메서드를 일회성으로 구현할 때 사용됩니다.
주요 특징
- 이름 없음: 생성자가 존재하지 않으며, 부모 클래스의 이름이나 인터페이스의 이름을 빌려 생성합니다.
- 일회성: 특정 위치에서 즉시 생성되어 사용되고 사라지므로 재사용이 불가능합니다.
- 코드 간결화: 별도의 클래스 파일을 생성하지 않아도 되므로 클래스 계층 구조를 단순하게 유지할 수 있습니다.
2. 익명 클래스의 선언 구조 및 문법
익명 클래스는 주로 상속(extends) 또는 인터페이스 구현(implements)을 기반으로 작성됩니다.
// 인터페이스 또는 클래스 참조변수 = new 부모클래스/인터페이스() {
// @Override
// void 메소드() {
// // 구현 내용
// }
// };
위 구조에서 보듯 new 키워드 뒤에 오는 것은 생성자가 아니라, 해당 인터페이스를 구현하거나 클래스를 상속받겠다는 선언과 동시에 몸체(body)를 여는 형태입니다.
3. 내부 클래스의 종류와 익명 클래스의 위치
자바의 내부 클래스는 크게 4가지로 나뉩니다. 익명 클래스가 이들 중 어디에 위치하며 어떤 차이가 있는지 아래 표를 통해 확인해 보세요.
| 종류 | 선언 위치 | 특징 및 특징 |
|---|---|---|
| 인스턴스 내부 클래스 | 외부 클래스의 멤버 변수 위치 | 외부 클래스의 인스턴스 생성 후 사용 가능 |
| 정적(Static) 내부 클래스 | 외부 클래스의 멤버 변수 위치 | 외부 클래스의 생성 없이 독립적으로 사용 가능 |
| 지역(Local) 내부 클래스 | 메서드 내부 | 해당 메서드 안에서만 유효함 |
| 익명(Anonymous) 클래스 | 메서드 내부 또는 변수 할당 시 | 이름이 없으며 선언과 동시에 객체 생성 (일회용) |
4. 익명 클래스 사용 시 주의사항: "Final" 제약
익명 클래스는 자신을 감싸고 있는 메서드의 지역 변수를 참조할 수 있습니다. 하지만 이때 중요한 제약 조건이 있습니다. 참조되는 지역 변수는 반드시 final이거나 effectively final(사실상 수정되지 않는) 상태여야 합니다.
자바 8 이전에는 명시적으로 final 키워드를 붙여야 했으나, 이후 버전에서는 값을 변경하지만 않는다면 자동으로 상수로 취급하여 접근을 허용합니다. 이는 메모리 관리(Stack vs Heap) 측면에서 익명 클래스 객체가 메서드보다 오래 살아남을 수 있기 때문에 발생하는 복사 메커니즘 때문입니다.
5. 현대 자바에서의 변화: 익명 클래스 vs 람다(Lambda)
자바 8에서 람다식이 도입되면서 익명 클래스의 입지가 다소 줄어들었습니다. 하지만 두 개념은 서로 보완적인 관계에 있습니다.
| 비교 항목 | 익명 클래스 | 람다식 (Lambda) |
|---|---|---|
| 대상 | 모든 인터페이스 및 클래스(추상 포함) | 함수형 인터페이스 (메서드 1개) |
키워드 this |
익명 클래스 자신을 가리킴 | 람다를 포함하는 외부 클래스를 가리킴 |
| 바이트코드 | 새로운 .class 파일 생성 | invokedynamic 방식을 통한 최적화 |
6. 실무에서의 활용 사례
- GUI 이벤트 처리: Android의
OnClickListener나 Swing의ActionListener구현 시 매우 흔하게 사용됩니다. - 정렬 (Comparator):
Collections.sort()사용 시 사용자 정의 정렬 기준을 즉석에서 만들 때 유용합니다. - 스레드 생성:
new Thread(new Runnable() { ... })와 같이 일회성 스레드 작업을 수행할 때 사용합니다.
결론: 왜 익명 클래스를 알아야 하는가?
람다식이 더 간결하긴 하지만, 여러 개의 메서드를 오버라이딩해야 하거나 추상 클래스를 상속받아야 하는 경우에는 여전히 익명 클래스가 유일한 해답입니다. 자바의 객체지향 설계를 깊이 있게 이해하고 유지보수가 쉬운 코드를 작성하기 위해서는 익명 클래스의 동작 방식을 정확히 파악하는 것이 필수적입니다.
출처 및 참고문헌
- Oracle Java Documentation: Inner Class Definitions
- Herbert Schildt, "Java: The Complete Reference", 12th Edition
- Cay S. Horstmann, "Core Java Volume I--Fundamentals"
'Language > Java' 카테고리의 다른 글
| [JAVA] 자바의 뿌리, Object 클래스가 모든 객체의 정점에 서 있는 이유와 철학적 배경 (0) | 2026.01.16 |
|---|---|
| [JAVA] 자바가 다중 상속을 포기하고 '순수성'을 선택한 진짜 이유 (0) | 2026.01.16 |
| [JAVA] Java 내부 클래스(Inner Class)의 완벽 이해 : 효율적인 구조 설계의 핵심 (0) | 2026.01.16 |
| [JAVA] Java 8의 혁명, Default 메서드 : 왜 인터페이스가 구현체를 가지게 되었을까? (0) | 2026.01.16 |
| [JAVA] 인터페이스, 왜 단순한 설계를 넘어 '생존 전략'인가? (0) | 2026.01.16 |