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를 사용하면 (그리고 불행히도 우리는 모두 자주 사용하지만) 하나라고 주장 할 수 있습니다.
답변
익명 클래스를위한 가이드 라인.
-
익명 클래스가 동시에 선언되고 초기화됩니다.
-
익명 클래스는 하나의 클래스 또는 인터페이스 resp로만 확장하거나 구현해야합니다.
-
익명 클래스에는 이름이 없으므로 한 번만 사용할 수 있습니다.
예 :
button.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent arg0) {
// TODO Auto-generated method stub
}
});