# Coding/Java

자바 내부클래스 익명클래스

hxodoo.cookie 2023. 9. 25. 23:40

자바의 내부클래스와 익명클래스는 코드의 간결함과 다형성의 미덕을 증명하는데 중요한 역할을 합니다. 이 글에서는 자바 내부클래스와 익명클래스에 대해 자세히 알아보겠습니다.

 

 

 

내부 클래스 (Inner Classes)

내부 클래스란 다른 클래스 내부에 정의된 클래스로, 외부 클래스의 멤버 변수 및 메서드에 쉽게 접근할 수 있습니다. 이는 코드의 캡슐화와 재사용성을 높이는 데 도움을 줍니다.

 

 

내부 클래스의 종류

자바의 내부 클래스는 크게 네 가지 종류로 나뉩니다.

 

 

1. 멤버 내부 클래스 (Member Inner Class)

멤버 내부 클래스는 외부 클래스의 인스턴스와 관련이 있으며 주로 인스턴스 변수나 메서드에 접근할 때 사용됩니다. 이 내부 클래스는 외부 클래스의 인스턴스 생성 후에 사용될 수 있고, 외부 클래스의 멤버 변수와 메서드와 함께 사용됩니다. 

 

 class Outer {
     int outerVar;

     class Inner {
         void display() {
             System.out.println("OuterVar: " + outerVar);
         }
     }
 }

 

 

2. 정적 내부 클래스 (Static Inner Class)

정적 내부클래스는 외부 클래스의 정적 멤버 변수나 메서드에 접근할 때 사용됩니다. 정적 내부클래스는 외부 클래스의 인스턴스를 생성하지 않고도 사용할 수 있으며, 다른 클래스에서도 독립적으로 인스턴스화할 수 있습니다.

 

 
 class Outer {
     static class StaticInner {
         void display() {
             System.out.println("This is a static inner class.");
         }
     }
 }

 

 

3. 지역 내부 클래스 (Local Inner Class)

지역 내부클래스는 메서드 내부에서만 정의되고 사용되는 클래스입니다. 해당 메서드 또는 블록 내에서만 유효하기 때문에 주로 해당 메서드 내부에서만 필요한 클래스를 정의할 때 사용됩니다.

 

 
 class Outer {
     void display() {
         class LocalInner {
             void show() {
                 System.out.println("Local inner class.");
             }
         }

         LocalInner inner = new LocalInner();
         inner.show();
     }
 }

 

 

4. 익명 내부 클래스 (Anonymous Inner Class)

익명 내부클래스는 이름이 없는 내부클래스로주로 인터페이스나 추상 클래스를 구현하는 데 사용됩니다익명 내부클래스는 코드를 간결하게 작성할  있으며 번만 사용되는 경우에 적합합니다

 

 
 interface Greeting {
     void greet();
 }

 class MyOuter {
     void sayHello() {
         Greeting greeting = new Greeting() {
             public void greet() {
                 System.out.println("Hello, World!");
             }
         };
         greeting.greet();
     }
 }

 

 

 


내부 클래스의 장점

내부 클래스는 자바 프로그래밍에서 코드 구조와 유지보수를 개선하고, 특별한 상황에서 유용한 패턴을 제공하는 중요한 도구 중 하나입니다. 내부 클래스의 장점을 캡슐화와 코드 정리, 외부 클래스와의 쉬운 접근, 그리고 특별한 상황에서의 활용에 초점을 맞추어 살펴보겠습니다.

 

 

1. 캡슐화와 코드 정리

내부 클래스는 외부 클래스 내부에서 정의되기 때문에, 관련된 코드를 한 곳에 묶을 수 있습니다. 이는 코드의 캡슐화를 촉진하고, 관련된 기능을 논리적으로 그룹화하여 코드를 더 읽기 쉽게 만듭니다.

 

class ShoppingCart {
    private List<Item> items;

    // 내부 클래스를 사용하여 아이템 관리 코드를 그룹화
    class Item {
        private String name;
        private double price;

        public Item(String name, double price) {
            this.name = name;
            this.price = price;
        }

        // Getter 및 Setter 메서드
    }

    // 아이템 추가 및 삭제 메서드
}

 

 

2. 외부 클래스와의 쉬운 접근

내부 클래스는 외부 클래스의 멤버 변수 및 메서드에 쉽게 접근할 수 있습니다. 이로 인해 내부 클래스는 외부 클래스의 상태를 공유하고 조작하는 데 용이합니다. 

 

class Outer {
    private int outerData;

    class Inner {
        void displayOuterData() {
            System.out.println("Outer Data: " + outerData);
        }
    }
}

 

 

3. 특별한 상황에서 사용 가능한 유용한 패턴

내부 클래스는 특별한 상황에서 유용한 패턴을 제공합니다. 예를 들어, 이벤트 리스너, 스레드, 익명 클래스 등을 구현할 때 내부 클래스를 활용할 수 있습니다.

 

// 이벤트 리스너를 내부 클래스로 구현하는 예시
button.addActionListener(new ActionListener() {
    public void actionPerformed(ActionEvent e) {
        // 버튼 클릭 시 수행할 동작
    }
});

 

 

:: 내부 클래스는 자바 프로그래밍에서 코드의 구조를 개선하고, 캡슐화를 촉진하며, 특별한 상황에서 유용한 패턴을 제공하는 강력한 기능입니다. 이를 통해 코드의 가독성을 높이고 유지보수성을 개선할 수 있으며, 특히 복잡한 작업을 수행하는 데 도움이 됩니다.

 

 

 


내부 클래스의 사용 예시

 

 

예시 코드: GUI 프로그래밍에서의 내부 클래스 활용

 

import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class MyGUIApp {
    public static void main(String[] args) {
        JFrame frame = new JFrame("내부 클래스 예시");

        JButton button = new JButton("클릭하세요");
        button.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                JOptionPane.showMessageDialog(frame, "버튼이 클릭되었습니다.");
            }
        });

        frame.add(button);
        frame.setSize(300, 200);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
    }
}

 

 

:: GUI 애플리케이션을 개발할 때, 내부 클래스는 윈도우, 패널, 버튼 등의 UI 구성 요소와 관련된 이벤트 처리를 쉽게 구현할 수 있는 방법을 제공합니다.

 

 

 

 

예시 코드: 컬렉션과 반복자 (Iterator) 패턴에서의 내부 클래스 사용

 

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class MyCollection {
    private List<String> items = new ArrayList<>();

    public void addItem(String item) {
        items.add(item);
    }

    public Iterator<String> iterator() {
        class MyIterator implements Iterator<String> {
            private int currentIndex = 0;

            public boolean hasNext() {
                return currentIndex < items.size();
            }

            public String next() {
                return items.get(currentIndex++);
            }
        }

        return new MyIterator();
    }
}

 

 

:: 컬렉션 클래스와 반복자 패턴을 사용할 때, 내부 클래스를 활용하면 컬렉션 내의 요소에 쉽게 접근하고 조작할 수 있습니다.

 

 

 

 

예시 코드: 이벤트 리스너 처리를 위한 내부 클래스

 

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;

public class MyEventHandler {
    public static void main(String[] args) {
        JFrame frame = new JFrame("이벤트 처리 예시");

        JButton button = new JButton("클릭하세요");
        button.addActionListener(new MyActionListener());

        frame.add(button);
        frame.setSize(300, 200);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
    }

    static class MyActionListener implements ActionListener {
        public void actionPerformed(ActionEvent e) {
            System.out.println("버튼이 클릭되었습니다.");
        }
    }
}

 

 

:: 이벤트 리스너를 처리할 때, 내부 클래스를 사용하면 이벤트 핸들러를 쉽게 정의하고 이벤트 소스와 연결할 수 있습니다.

 

 

 


익명 내부클래스(Anonymous Inner Class)

자바 프로그래밍에서 익명 클래스는 코드를 간결하게 작성하고, 함수형 프로그래밍 스타일을 적용하는 데 도움을 주는 기능입니다.

 

 

익명 클래스의 정의와 특징

익명 클래스는 자바에서 내부 클래스(Inner Class)의 일종으로, 이름이 없는 클래스입니다. 클래스 정의와 인스턴스 생성을 동시에 수행하는 클래스로, 주로 한 번만 사용되는 간단한 클래스를 정의하고 인스턴스화하는 데 사용되거나 인터페이스나 추상 클래스를 구현할  사용됩니다. 익명 클래스는 코드의 간결성과 가독성을 향상시키며, 자바의 객체지향 프로그래밍에 적합한 유용한 도구입니다.

 

▷▶ 익명 클래스의 특징

  • 이름이 없다: 클래스명이나 인터페이스명 없이 정의되므로 이름이 없습니다. 익명 내부클래스는 이름이 없기 때문에 한 번만 사용되고 다른 곳에서 재사용되지 않습니다. 이는 코드의 재사용성을 낮출 수 있지만, 특정한 상황에서 유용합니다.
  • 인스턴스화와 동시에 정의: 클래스의 정의와 인스턴스 생성이 동시에 이루어집니다. 이를 통해 코드를 간결하게 작성할 수 있습니다.
  • 외부 변수 접근: 외부 클래스의 변수에 쉽게 접근할 수 있습니다.
  • 주로 한 번만 사용: 주로 한 번 사용되고 더 이상 재사용되지 않는 경우에 적합합니다.
  •  

 

 

 


익명 클래스의 생성과 활용

익명 클래스는 주로 인터페이스나 추상 클래스의 구현체를 정의하고 생성하는 데 사용됩니다. 예시를 통해 익명 클래스의 생성과 활용을 살펴보겠습니다.

 

 

예시 코드: 인터페이스의 구현체 정의

 

// 인터페이스 정의
interface Greeting {
    void greet();
}

public class AnonymousClassExample {
    public static void main(String[] args) {
        // 익명 클래스로 Greeting 인터페이스의 구현체 생성
        Greeting greeting = new Greeting() {
            @Override
            public void greet() {
                System.out.println("안녕하세요!");
            }
        };

        // 익명 클래스의 메서드 호출
        greeting.greet();
    }
}

 

 

 

 

예시 코드: 버튼 이벤트 처리를 위한 ActionListener 구현

 

import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class AnonymousInnerClassExample {
    public static void main(String[] args) {
        JFrame frame = new JFrame("익명 내부클래스 예제");
        JButton button = new JButton("클릭하세요!");

        // ActionListener를 익명 내부클래스로 구현
        button.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                JOptionPane.showMessageDialog(null, "버튼이 클릭되었습니다.");
            }
        });

        frame.add(button);
        frame.setSize(300, 200);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
    }
}

 

 

:: ActionListener를 구현하는 별도의 클래스를 정의하지 않고 익명 내부클래스를 사용하여 버튼의 클릭 이벤트를 처리할 수 있습니다. 이로 인해 코드가 간결해지고 이벤트 핸들러를 버튼에 직접 연결할 수 있습니다.

 

 

 


익명 클래스와 함수형 인터페이스

자바 8부터 함수형 프로그래밍을 지원하기 위해 함수형 인터페이스가 도입되었습니다. 익명 클래스는 함수형 인터페이스의 객체를 생성하는데 자주 사용됩니다. 예시 코드를 통해 함수형 인터페이스와 익명 클래스의 관계를 살펴보겠습니다.

 

 

// 함수형 인터페이스 정의
interface MathOperation {
    int operate(int a, int b);
}

public class AnonymousAndFunctionalInterface {
    public static void main(String[] args) {
        // 덧셈 연산을 수행하는 익명 클래스
        MathOperation addition = new MathOperation() {
            @Override
            public int operate(int a, int b) {
                return a + b;
            }
        };

        // 뺄셈 연산을 수행하는 익명 클래스
        MathOperation subtraction = new MathOperation() {
            @Override
            public int operate(int a, int b) {
                return a - b;
            }
        };

        // 연산 결과 출력
        System.out.println("덧셈 결과: " + addition.operate(5, 3));
        System.out.println("뺄셈 결과: " + subtraction.operate(5, 3));
    }
}

 

 

:: 자바의 익명 클래스는 코드의 간결성과 가독성을 향상시키며, 함수형 프로그래밍 스타일을 적용하는 데 매우 유용한 도구입니다. 이러한 특징을 활용하여 간단한 클래스나 함수형 인터페이스의 객체를 생성하고 활용할 수 있습니다. 

 

 

 


익명 클래스의 장단점

 

 

1. 익명클래스의 장점

 

 

코드의 간결성과 가독성 향상

익명 클래스는 작은 크기의 클래스나 인터페이스를 간단하게 정의하고 인스턴스화할 수 있는 방법을 제공합니다. 이로 인해 코드가 더 간결하고 가독성이 향상됩니다. 예를 들어, 익명 클래스를 사용하여 이벤트 리스너를 정의하면 불필요한 클래스 파일을 생성하지 않고도 이벤트 처리를 간단하게 구현할 수 있습니다.

 

 

button.addActionListener(new ActionListener() {
    public void actionPerformed(ActionEvent e) {
        // 버튼 클릭 시 수행할 동작
    }
});

 

 

 

▶ 한 번만 사용되는 클래스의 경우 효율적

익명 클래스는 주로 한 번만 사용되고 재사용되지 않는 경우에 유용합니다. 클래스 파일을 별도로 생성하지 않고 인스턴스를 생성할 수 있으므로, 작고 간단한 클래스의 경우 메모리 공간과 파일 시스템 리소스를 절약할 수 있습니다.

 

 

// 한 번만 사용되는 인터페이스를 익명 클래스로 구현
MathOperation addition = new MathOperation() {
    @Override
    public int operate(int a, int b) {
        return a + b;
    }
};

// 별도의 클래스 정의 없이 간단한 연산 구현 가능
int result = addition.operate(5, 3);

 

 

 

 

2. 익명 클래스의 단점

 

 

▶ 제한된 활용 범위

익명 클래스는 주로 간단한 구현체를 다루는 데 사용됩니다. 복잡한 로직이 필요한 경우에는 별도의 클래스로 분리하는 것이 더 바람직합니다. 익명 클래스는 클래스 선언과 인스턴스 생성이 동시에 이루어지기 때문에, 복잡한 로직을 포함하면 코드가 복잡해질 우려가 있습니다.

 

 

▶ 상속과 인터페이스 동시 구현 제한

익명 클래스에서는 하나의 클래스 또는 인터페이스만 구현하거나 상속할 수 있습니다. 다중 상속이 필요한 경우에는 익명 클래스로 해결하기 어려울 수 있습니다.

 

 

 

※ 익명 클래스 작성 시 주의사항

재사용 불가
익명 내부클래스는 한 번만 사용할 수 있으며, 다른 곳에서 재사용할 수 없습니다. 따라서 동일한 기능을 여러 곳에서 사용해야 할 경우에는 별도의 클래스를 정의하는 것이 더 나을 수 있습니다.


외부 변수 접근
익명 클래스에서 외부 변수를 접근할 때에는 해당 변수가 final 또는 effectively final이어야 합니다. 이는 익명 클래스의 인스턴스가 생성될 때 해당 변수를 복사하여 저장하기 때문입니다.

 

람다 표현식 대체 고려

자바 8부터는 람다 표현식이 도입되어 익명 클래스를 대체하는 더 간결한 방법을 제공합니다. 코드의 가독성과 간결성을 높이려면 람다 표현식을 고려해 보는 것이 좋습니다.

 

 

 

int x = 10;
ActionListener listener = new ActionListener() {
    public void actionPerformed(ActionEvent e) {
        System.out.println(x); // x는 final 또는 effectively final이어야 함
    }
};

 

 

:: 자바의 익명 클래스는 코드의 간결성과 가독성 향상을 위한 강력한 도구로, 한 번만 사용되는 간단한 클래스나 인터페이스를 효율적으로 다루는 데 적합합니다. 그러나 복잡한 로직이 필요한 경우에는 익명 클래스의 한계를 고려하고, 람다 표현식과 같은 더 간결한 대안을 고려해야 합니다. 주의사항을 잘 숙지하고 상황에 맞게 익명 클래스를 활용하면 코드 작성과 유지보수가 더 효율적으로 이루어질 것입니다.

 

 

 


내부 클래스 vs 익명 클래스

자바 프로그래밍에서 내부 클래스(Inner Classes)와 익명 클래스(Anonymous Inner Classes)는 코드 구조와 가독성을 개선하는 데 도움을 주는 중요한 도구입니다. 이 글에서는 각각의 클래스의 장단점을 비교하고, 어떤 상황에서 어떤 클래스를 선택해야 하는지에 대해 자세히 알아보겠습니다.

 

 

구분 내부 클래스 익명 클래스
장점 - 코드의 가독성과 유지보수성 향상
- 외부 변수 접근 용이
- 코드의 간결성과 가독성 향상
- 한 번만 사용되는 클래스의 경우 효율적
단점 - 불필요한 클래스 파일 생성 - 제한된활용범위 

 

 

어떤 클래스를 선택할 것인가?

내부 클래스를 선택할 때:

  • 코드의 구조화와 가독성을 높이고자 할 때.
  • 여러 메서드에서 공통으로 사용되는 클래스를 정의할 때.
  • 외부 변수에 접근해야 할 때.


익명 클래스를 선택할 때:

  • 한 번만 사용되는 간단한 클래스 또는 인터페이스를 구현할 때.
  • 코드를 간결하게 유지하고자 할 때.
  • 함수형 인터페이스의 객체를 생성하고자 할 때.

 

 

:: 내부 클래스와 익명 클래스는 각각의 장단점을 가지고 있으며, 어떤 클래스를 선택할지는 상황에 따라 다릅니다. 내부 클래스는 코드의 구조화와 가독성을 높이고자 할 때 유용하며, 익명 클래스는 간단한 클래스나 인터페이스를 간결하게 구현하고자 할 때 효과적입니다. 프로젝트의 요구사항과 코드의 복잡성을 고려하여 적절한 클래스를 선택해야 합니다.

 

 

 


자바 내부클래스와 익명 내부클래스는 코드의 간결성과 다형성을 활용하는데 중요한 도구입니다. 내부클래스를 통해 클래스를 캡슐화하고 다형성을 구현할 수 있으며, 익명 내부클래스를 사용하면 코드의 간결성을 높일 수 있습니다. 하지만 익명 내부클래스는 재사용이 어려우므로 적절한 상황에서 사용해야 합니다. 코드를 작성할 때 내부클래스와 익명 내부클래스를 적절히 활용하여 보다 효율적이고 가독성 있는 코드를 작성할 수 있습니다.