[java] Java에서 익명 내부 클래스는 어떻게 사용됩니까?

Java에서 익명 클래스의 사용은 무엇입니까? 익명 클래스의 사용이 Java의 장점 중 하나라고 말할 수 있습니까?



답변

“익명 클래스”란 익명의 내부 클래스 를 의미 합니다.

익명의 내부 클래스는 클래스를 실제로 서브 클래스하지 않고도 메소드 재정의와 같은 특정 “엑스트라”를 가진 객체의 인스턴스를 만들 때 유용 할 수 있습니다.

이벤트 리스너를 연결하는 바로 가기로 사용하는 경향이 있습니다.

button.addActionListener(new ActionListener() {
    @Override
    public void actionPerformed(ActionEvent e) {
        // do something
    }
});

이 메소드를 사용하면 구현하는 추가 클래스를 만들 필요가 없으므로 코딩이 조금 빨라 ActionListener집니다. 실제로 별도의 클래스를 만들지 않고도 익명의 내부 클래스를 인스턴스화 할 수 있습니다.

나는이 기술을 전체 수업을 불필요하게하는 “신속하고 더러운”작업에만 사용합니다. 정확히 같은 일을 수행하는 여러 익명의 내부 클래스가 있으면 실제 클래스, 즉 내부 클래스 또는 별도의 클래스로 리팩토링되어야합니다.


답변

익명의 내부 클래스는 효과적으로 닫히므로 람다 식 또는 “위임”을 에뮬레이트하는 데 사용할 수 있습니다. 예를 들어 다음 인터페이스를 사용하십시오.

public interface F<A, B> {
   B f(A a);
}

이것을 익명으로 사용하여 Java에서 일급 함수 를 작성할 수 있습니다 . 주어진 목록에서 i보다 큰 첫 번째 숫자를 반환하거나 숫자가 크지 않은 경우 i를 반환하는 다음과 같은 메서드가 있다고 가정 해 봅시다.

public static int larger(final List<Integer> ns, final int i) {
  for (Integer n : ns)
     if (n > i)
        return n;
  return i;
}

그런 다음 주어진 목록에서 i보다 작은 첫 번째 숫자를 반환하거나 더 작은 숫자가없는 경우 i를 반환하는 다른 방법이 있습니다.

public static int smaller(final List<Integer> ns, final int i) {
   for (Integer n : ns)
      if (n < i)
         return n;
   return i;
}

이 방법들은 거의 동일합니다. 일급 함수 유형 F를 사용하여 다음과 같이 하나의 메소드로 다시 작성할 수 있습니다.

public static <T> T firstMatch(final List<T> ts, final F<T, Boolean> f, T z) {
   for (T t : ts)
      if (f.f(t))
         return t;
   return z;
}

익명 클래스를 사용하여 firstMatch 메소드를 사용할 수 있습니다.

F<Integer, Boolean> greaterThanTen = new F<Integer, Boolean> {
   Boolean f(final Integer n) {
      return n > 10;
   }
};
int moreThanMyFingersCanCount = firstMatch(xs, greaterThanTen, x);

이것은 실제로 고안된 예이지만, 값처럼 함수를 전달할 수 있다는 것은 매우 유용한 기능이라는 것을 쉽게 알 수 있습니다. Joel 자신의 “프로그래밍 언어가이를 수행 할 수 있습니까?”를 참조하십시오 .

이 스타일의 Java 프로그래밍을위한 멋진 라이브러리 : Functional Java.


답변

익명의 내부 클래스는 다음 시나리오에서 사용됩니다.

1.) 재정의 (하위 분류)의 경우 현재 케이스를 제외하고 클래스 정의를 사용할 수없는 경우 :

class A{
   public void methodA() {
      System.out.println("methodA");
    }
}
class B{
    A a = new A() {
     public void methodA() {
        System.out.println("anonymous methodA");
     }
   };
}

2.) 인터페이스 구현이 현재의 경우에만 인터페이스 구현이 필요한 경우 :

interface interfaceA{
   public void methodA();
}
class B{
   interfaceA a = new interfaceA() {
     public void methodA() {
        System.out.println("anonymous methodA implementer");
     }
   };
}

3.) 인수 정의 익명 내부 클래스 :

 interface Foo {
   void methodFoo();
 }
 class B{
  void do(Foo f) { }
}

class A{
   void methodA() {
     B b = new B();
     b.do(new Foo() {
       public void methodFoo() {
         System.out.println("methodFoo");
       } 
     });
   } 
 } 


답변

때때로 맵 인스턴스화를위한 구문 핵으로 사용합니다.

Map map = new HashMap() {{
   put("key", "value");
}};

vs

Map map = new HashMap();
map.put("key", "value");

많은 put 문을 수행 할 때 중복성을 줄입니다. 그러나 외부 클래스를 원격으로 직렬화해야 할 때이 문제가 발생했습니다.


답변

일반적으로 장황한 콜백 형태로 사용됩니다.

나는 그들이 그것을 가지고 있지 않고 매번 명명 된 클래스를 만들어야하는 것에 비해 이점이라고 말할 수 있다고 가정하지만 비슷한 개념은 다른 언어 (클로저 또는 블록)에서 훨씬 잘 구현됩니다.

다음은 스윙 예제입니다

myButton.addActionListener(new ActionListener(){
    public void actionPerformed(ActionEvent e) {
        // do stuff here...
    }
});

여전히 장황하지만 장황하지만 모든 상황에서 리스너에 대해 명명 된 클래스를 정의하는 것보다 훨씬 좋습니다 (상황과 재사용에 따라 다르지만 여전히 더 나은 방법 일 수 있습니다)


답변

리스너, 런너 블 (스레드 생성) 등 다른 함수 내부의 특정 목적을 위해 클래스를 작성해야하는 상황에서 사용합니다.

아이디어는 함수 코드 내부에서 호출하므로 다른 곳에서는 참조하지 않으므로 이름을 지정할 필요가 없습니다. 컴파일러는 그것들을 열거합니다.

그것들은 본질적으로 구문 설탕이며 일반적으로 더 커지면 다른 곳으로 옮겨야합니다.

Java의 장점 중 하나인지 확실하지 않지만, Java를 사용하면 (그리고 불행히도 우리는 모두 자주 사용하지만) 하나라고 주장 할 수 있습니다.


답변

익명 클래스를위한 가이드 라인.

  1. 익명 클래스가 동시에 선언되고 초기화됩니다.

  2. 익명 클래스는 하나의 클래스 또는 인터페이스 resp로만 확장하거나 구현해야합니다.

  3. 익명 클래스에는 이름이 없으므로 한 번만 사용할 수 있습니다.

예 :

button.addActionListener(new ActionListener(){

            public void actionPerformed(ActionEvent arg0) {
        // TODO Auto-generated method stub

    }
});