익명클래스란? 사용법과 사용이유

GarionNachal·2025년 5월 6일
0

JAVA, Springboot

목록 보기
4/6
post-thumbnail

1. 익명클래스란?

익명클래스(Anonymous Class)는 말 그대로 이름이 없는 클래스를 의미합니다. 익명클래스는 내부 클래스(Inner Class)의 일종으로, 클래스의 선언과 객체의 생성을 동시에 수행합니다. 따라서 단 한 번만 사용되는 일회용 클래스로, 프로그램에서 임시적으로 사용되고 버려지는 객체를 구현할 때 주로 활용됩니다.

익명클래스는 이름이 없기 때문에 생성자를 가질 수 없으며, 클래스 정의와 동시에 객체가 생성됩니다. 주로 상속이나 인터페이스 구현을 통해 일시적으로 필요한 기능을 재정의하여 사용합니다.

2. 익명클래스의 특징

  1. 이름이 없음: 이름이 없기 때문에 재사용이 불가능합니다.
  2. 선언과 동시에 인스턴스화: 클래스 정의와 객체 생성이 동시에 이루어집니다.
  3. 일회성 사용: 한 번만 사용되고 버려지는 일회용 클래스입니다.
  4. 제약사항:
    • 생성자를 가질 수 없습니다.
    • 하나의 클래스나 인터페이스만 상속 또는 구현할 수 있습니다.
    • 새로 정의한 메서드는 외부에서 호출이 불가능합니다.

3. 익명클래스 사용법

익명클래스는 크게 두 가지 방식으로 사용됩니다:

1) 클래스 상속을 통한 익명 자식 객체 생성

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(); // 에러! 외부에서 접근 불가능
    }
}

2) 인터페이스 구현을 통한 익명 구현 객체 생성

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(); // "달리고 있습니다." 출력
    }
}

3) 익명클래스의 선언 위치

익명클래스는 다음과 같은 위치에서 선언할 수 있습니다:

  1. 필드의 초기값으로 사용

    Copypublic class Example {
        // 필드에 익명 객체 할당
        private Button button = new Button() {
            @Override
            public void click() {
                System.out.println("버튼이 클릭되었습니다.");
            }
        };
    }
    
  2. 지역 변수의 초기값으로 사용

    Copypublic void method() {
        // 지역 변수에 익명 객체 할당
        Runnable task = new Runnable() {
            @Override
            public void run() {
                System.out.println("작업을 실행합니다.");
            }
        };
        task.run();
    }
    
  3. 메서드의 매개변수로 사용

    Copypublic void startTask(Runnable runnable) {
        runnable.run();
    }
    
    public void example() {
        // 메서드 인자로 익명 객체 전달
        startTask(new Runnable() {
            @Override
            public void run() {
                System.out.println("인자로 전달된 작업을 실행합니다.");
            }
        });
    }
    

4. 익명클래스를 사용하는 이유

익명클래스를 사용하는 주요 이유는 다음과 같습니다:

  1. 코드 간결성: 별도의 클래스 파일을 만들지 않고도 필요한 기능을 바로 구현할 수 있어 코드가 간결해집니다.

  2. 일회성 기능 구현: 프로그램에서 단 한 번만 사용되는 클래스를 위해 별도의 파일을 만들 필요가 없습니다.

    Copy// 일회성 이벤트 처리
    button.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            System.out.println("버튼이 클릭되었습니다.");
        }
    });
    
  3. 유지보수 효율성: 재사용성이 없는 클래스를 위해 별도 파일을 관리할 필요가 없어 유지보수가 효율적입니다.

  4. 메모리 효율성: 필요할 때만 생성하고 사용 후 버려지므로 메모리 관리에 효율적입니다.

  5. 특정 기능의 확장: 기존 클래스나 인터페이스의 기능을 일시적으로 확장할 때 유용합니다.

5. 익명클래스 활용 예제

1) UI 이벤트 처리

익명클래스는 자바 스윙(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);
    }
}

2) 쓰레드 생성

쓰레드를 일회성으로 생성할 때도 익명클래스가 유용합니다:

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("메인 쓰레드는 계속 실행됩니다.");
    }
}

3) 컬렉션의 정렬

컬렉션을 정렬할 때 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);
        }
    }
}

6. 익명클래스와 람다식 비교

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("간결한 람다식");

람다식은 익명클래스보다 더 간결한 코드를 작성할 수 있게 해주지만, 여러 개의 추상 메서드를 가진 인터페이스는 람다식으로 구현할 수 없다는 제약이 있습니다.

7. 익명클래스의 제약사항

익명클래스를 사용할 때 알아두어야 할 몇 가지 제약사항이 있습니다:

  1. 생성자를 가질 수 없음: 이름이 없기 때문에 생성자를 정의할 수 없습니다.
  2. 하나의 클래스/인터페이스만 상속/구현 가능: 다중 상속이나 다중 인터페이스 구현이 불가능합니다.
  3. 외부 변수 접근 제약: 익명클래스에서 외부 지역 변수를 사용하려면 해당 변수는 final 또는 effectively final이어야 합니다.
  4. 새로 추가한 메서드 접근 불가: 익명클래스에서 새로 추가한 메서드는 외부에서 접근할 수 없습니다.
  5. 정적 멤버 선언 불가: 익명클래스 내부에서는 정적 멤버를 선언할 수 없습니다.

8. 익명클래스의 컴파일 결과

익명클래스를 사용하는 Java 파일을 컴파일하면 특별한 형태의 클래스 파일이 생성됩니다:

  • 기본 규칙: 외부클래스명$번호.class
  • 예: Main.java 파일에 2개의 익명클래스가 있다면 Main.classMain$1.classMain$2.class 파일이 생성됩니다.

9. 결론

익명클래스는 Java 프로그래밍에서 코드를 간결하게 만들고, 일회성 기능을 구현할 때 매우 유용한 도구입니다. 특히 이벤트 처리, 쓰레드 생성, 콜백 함수 구현 등 재사용 가능성이 낮은 기능을 구현할 때 적합합니다.

하지만 Java 8 이후에는 람다식이라는 더 간결한 방법이 도입되어, 함수형 인터페이스를 구현할 때는 람다식을 사용하는 것이 더 효율적입니다. 그럼에도 불구하고 익명클래스는 여전히 Java 프로그래밍의 중요한 개념으로, 람다식으로 대체할 수 없는 상황에서 여전히 유용하게 사용됩니다.

익명클래스의 핵심은 코드의 간결성과 유지보수의 효율성에 있습니다. 필요할 때 적절히 활용하여 더 깔끔하고 효율적인 코드를 작성하는 데 도움이 되길 바랍니다.

참고 자료

profile
AI를 꿈꾸는 BackEnd개발자

0개의 댓글