동일한 이름의 익명 클래스 이외의 방법을 호출 할 수없는 이유
-
05-07-2019 - |
문제
끝의 코드는 컴파일 오류를 생성합니다.
NotApplicable.java:7: run() in cannot be applied to (int)
run(42);
^
1 error
문제는 왜 그런가? Javac이 내가 run ()에게 전화를 걸고 있다고 생각하는 이유는 무엇입니까 (int bar). FOO (int bar)를 올바르게라고합니다. 왜 내가 적용 할 수없는 것을 사용해야합니까? this.run (42);? 버그입니까?
public class NotApplicable {
public NotApplicable() {
new Runnable() {
public void run() {
foo(42);
run(42);
// uncomment below to fix
//NotApplicable.this.run(42);
}
};
}
private void run(int bar) {
}
public void foo(int bar) {
}
}
해결책
코드 샘플의 동작에 대한 설명은 this
당신이 현재 "가장"내부에있는 클래스로 정의됩니다. 이 경우, 당신은 익명의 내부 클래스 내부에서 서브 클래스를 실행할 수 있고 일치하는 방법이 없습니다. run(int)
. 검색을 넓히려면 어느 것을 지정합니다 this
당신은 언급하여 사용하고 싶습니다 NotApplicable.this.run(42)
.
JVM은 다음과 같이 평가합니다.
this
-> 현재 인스턴스를 실행하고 있습니다 Runnable
방법으로 run()
NotApplicable.this
-> 현재 인스턴스를 실행하고 있습니다 NotApplicable
방법으로 run(int)
컴파일러는 메소드 이름과 일치하는 첫 번째 메소드에 대해 둥지 트리를 찾습니다. -이 설명을 위해 Djclayworth에 감사합니다
익명의 내부 클래스는 외부 클래스의 서브 클래스가 아닙니다. 이 관계로 인해 내부 클래스와 외부 클래스는 정확히 동일한 서명을 가진 메소드를 가질 수 있어야하며 가장 안쪽 코드 블록은 실행하려는 메소드를 식별 할 수 있어야합니다.
public class Outer{
public Outer() {
new Runnable() {
public void printit() {
System.out.println( "Anonymous Inner" );
}
public void run() {
printit(); // prints "Anonymous Inner"
this.printit(); //prints "Anonymous Inner"
// would not be possible to execute next line without this behavior
Outer.this.printit(); //prints "Outer"
}
};
}
public void printit() {
System.out.println( "Outer" );
}
}
다른 팁
중첩 클래스 사이에서 실행되는 메소드를 선택하는 규칙을 기억하는 한 상속 트리에서 메소드를 선택하는 규칙과 거의 동일합니다. 그것은 우리가 여기에 도착하는 것이 과부하가 아니라 숨어 있다는 것을 의미합니다. 이들 사이의 차이는 상속에서 방법을 이해하는 데 중요합니다.
Runnable이 서브 클래스로 선언 된 경우 run () 메소드는 부모의 run (int) 메소드를 숨 깁니다. 실행 요청 (...)은 Runnable에서 실행하려고 시도하지만 서명과 일치 할 수없는 경우 실패합니다. Foo는 아이에게 선언되지 않기 때문에 부모의 사람은 호출됩니다.
여기서도 같은 원칙이 일어나고 있습니다. "방법 숨기기"에 대한 참조를 찾아 보면 명확해야합니다.
이 때문입니다 run
당신이 입력 할 때 다시 고추되고 있습니다 new Runnable() {}
범위. 실행에 대한 모든 이전 바인딩은 접근 할 수 없게됩니다. 마치 당신이 이것을하는 것처럼 보입니다.
import java.util.*;
public class tmp
{
private int x = 20;
public static class Inner
{
private List x = new ArrayList();
public void func()
{
System.out.println(x + 10);
}
}
public static void main(String[] args)
{
(new Inner()).func();
}
}
컴파일러는 x
범위 스택 위로 올라가면 첫 번째 참조를 찾을 때 중단되고 유형이 호환되지 않는 것을 알 수 있습니다.
노트: 마치 마치 마치 아닙니다 할 수 없었습니다 이렇게하십시오 ... 단지 자신의 정신을 보존하기 위해서는 안됩니다.