익명클래스(Anonymous Class)는 말 그대로 이름이 없는 클래스를 의미합니다. 익명클래스는 내부 클래스(Inner Class)의 일종으로, 클래스의 선언과 객체의 생성을 동시에 수행합니다. 따라서 단 한 번만 사용되는 일회용 클래스로, 프로그램에서 임시적으로 사용되고 버려지는 객체를 구현할 때 주로 활용됩니다.
익명클래스는 이름이 없기 때문에 생성자를 가질 수 없으며, 클래스 정의와 동시에 객체가 생성됩니다. 주로 상속이나 인터페이스 구현을 통해 일시적으로 필요한 기능을 재정의하여 사용합니다.
익명클래스는 크게 두 가지 방식으로 사용됩니다:
Copy// 부모 클래스
class Animal {
public void sound() {
System.out.println("동물이 소리를 냅니다.");
}
}
public class Main {
public static void main(String[] args) {
// 익명 자식 객체 생성
Animal dog = new Animal() {
@Override
public void sound() {
System.out.println("개가 짖습니다.");
}
// 새로 정의한 메서드
public void run() {
System.out.println("개가 달립니다.");
}
}; // 세미콜론 필수!
dog.sound(); // "개가 짖습니다." 출력
// dog.run(); // 에러! 외부에서 접근 불가능
}
}
Copy// 인터페이스
interface Runnable {
void run();
}
public class Main {
public static void main(String[] args) {
// 익명 구현 객체 생성
Runnable runner = new Runnable() {
@Override
public void run() {
System.out.println("달리고 있습니다.");
}
}; // 세미콜론 필수!
runner.run(); // "달리고 있습니다." 출력
}
}
익명클래스는 다음과 같은 위치에서 선언할 수 있습니다:
필드의 초기값으로 사용
Copypublic class Example {
// 필드에 익명 객체 할당
private Button button = new Button() {
@Override
public void click() {
System.out.println("버튼이 클릭되었습니다.");
}
};
}
지역 변수의 초기값으로 사용
Copypublic void method() {
// 지역 변수에 익명 객체 할당
Runnable task = new Runnable() {
@Override
public void run() {
System.out.println("작업을 실행합니다.");
}
};
task.run();
}
메서드의 매개변수로 사용
Copypublic void startTask(Runnable runnable) {
runnable.run();
}
public void example() {
// 메서드 인자로 익명 객체 전달
startTask(new Runnable() {
@Override
public void run() {
System.out.println("인자로 전달된 작업을 실행합니다.");
}
});
}
익명클래스를 사용하는 주요 이유는 다음과 같습니다:
코드 간결성: 별도의 클래스 파일을 만들지 않고도 필요한 기능을 바로 구현할 수 있어 코드가 간결해집니다.
일회성 기능 구현: 프로그램에서 단 한 번만 사용되는 클래스를 위해 별도의 파일을 만들 필요가 없습니다.
Copy// 일회성 이벤트 처리
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("버튼이 클릭되었습니다.");
}
});
유지보수 효율성: 재사용성이 없는 클래스를 위해 별도 파일을 관리할 필요가 없어 유지보수가 효율적입니다.
메모리 효율성: 필요할 때만 생성하고 사용 후 버려지므로 메모리 관리에 효율적입니다.
특정 기능의 확장: 기존 클래스나 인터페이스의 기능을 일시적으로 확장할 때 유용합니다.
익명클래스는 자바 스윙(Swing)과 같은 GUI 프로그래밍에서 이벤트 처리에 많이 사용됩니다:
Copyimport javax.swing.*;
import java.awt.event.*;
public class ButtonExample {
public static void main(String[] args) {
JFrame frame = new JFrame("버튼 예제");
JButton button = new JButton("클릭하세요");
// 버튼 클릭 이벤트를 익명 클래스로 처리
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(frame, "버튼이 클릭되었습니다!");
}
});
frame.add(button);
frame.setSize(300, 200);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
쓰레드를 일회성으로 생성할 때도 익명클래스가 유용합니다:
Copypublic class ThreadExample {
public static void main(String[] args) {
// Runnable 인터페이스를 구현한 익명 클래스로 쓰레드 생성
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 5; i++) {
System.out.println("쓰레드 실행 중... " + i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
thread.start();
System.out.println("메인 쓰레드는 계속 실행됩니다.");
}
}
컬렉션을 정렬할 때 Comparator를 익명클래스로 구현할 수 있습니다:
Copyimport java.util.*;
public class SortExample {
public static void main(String[] args) {
List<String> names = new ArrayList<>();
names.add("김철수");
names.add("이영희");
names.add("박지민");
// 익명 클래스로 Comparator 구현
Collections.sort(names, new Comparator<String>() {
@Override
public int compare(String s1, String s2) {
return s1.length() - s2.length(); // 문자열 길이로 정렬
}
});
for (String name : names) {
System.out.println(name);
}
}
}
Java 8부터 도입된 람다식(Lambda Expression)은 익명클래스를 더욱 간결하게 표현할 수 있는 방법입니다. 특히 함수형 인터페이스(단 하나의 추상 메서드만 가진 인터페이스)를 구현할 때 유용합니다.
Copy// 익명클래스 사용
Runnable runnable1 = new Runnable() {
@Override
public void run() {
System.out.println("익명클래스로 구현");
}
};
// 람다식 사용
Runnable runnable2 = () -> {
System.out.println("람다식으로 구현");
};
// 더 간결한 람다식
Runnable runnable3 = () -> System.out.println("간결한 람다식");
람다식은 익명클래스보다 더 간결한 코드를 작성할 수 있게 해주지만, 여러 개의 추상 메서드를 가진 인터페이스는 람다식으로 구현할 수 없다는 제약이 있습니다.
익명클래스를 사용할 때 알아두어야 할 몇 가지 제약사항이 있습니다:
익명클래스를 사용하는 Java 파일을 컴파일하면 특별한 형태의 클래스 파일이 생성됩니다:
외부클래스명$번호.class
Main.java
파일에 2개의 익명클래스가 있다면 Main.class
, Main$1.class
, Main$2.class
파일이 생성됩니다.익명클래스는 Java 프로그래밍에서 코드를 간결하게 만들고, 일회성 기능을 구현할 때 매우 유용한 도구입니다. 특히 이벤트 처리, 쓰레드 생성, 콜백 함수 구현 등 재사용 가능성이 낮은 기능을 구현할 때 적합합니다.
하지만 Java 8 이후에는 람다식이라는 더 간결한 방법이 도입되어, 함수형 인터페이스를 구현할 때는 람다식을 사용하는 것이 더 효율적입니다. 그럼에도 불구하고 익명클래스는 여전히 Java 프로그래밍의 중요한 개념으로, 람다식으로 대체할 수 없는 상황에서 여전히 유용하게 사용됩니다.
익명클래스의 핵심은 코드의 간결성과 유지보수의 효율성에 있습니다. 필요할 때 적절히 활용하여 더 깔끔하고 효율적인 코드를 작성하는 데 도움이 되길 바랍니다.