2008-10-31 3 views
2

같은 이름의 익명 클래스의 외부에 메소드를 호출 할 수 없습니다? javac이 run()을 호출하고 run (int bar)을 찾지 못하는 이유는 무엇입니까? foo (int bar)를 올바르게 호출했습니다. 왜 내가 NotApplicable.this.run (42);을 사용해야합니까? 그게 버그 야? 당신이 new Runnable() {} 범위를 입력 할 때 run이 다시 선언되고 있기 때문에이유는 끝이 코드는 컴파일 오류가 발생

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) { 
    } 
} 

답변

16

코드 샘플의 동작에 대한 설명은 현재 this이 현재 "가장"내부에있는 클래스로 정의되어 있습니다. 이 경우 익명의 내부 클래스에서 "대부분"실행 클래스 하위 클래스이며 일치하는 메서드가 없습니다 run(int). 검색 범위를 넓히려면 NotApplicable.this.run(42)을 사용하여 this을 사용 하시겠습니까?를 지정하십시오.

으로 평가합니다 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"); 
    } 
} 
+0

foo (int bar)가 올바르게 호출 된 이유를 설명하지 않았습니다. – Pyrolistical

+2

"이 동작은 두 메서드의 이름이 '실행되지 않은 경우에도 표시됩니다'"부분을 제외하고 올바른 답변입니다. 컴파일러는 메소드의 이름과 일치하는 첫 번째 메소드의 중첩 트리를 검색합니다. – DJClayworth

0

이다. 이전의 모든 바인딩을 액세스 할 수 없게됩니다. 그 첫 번째 참조를 찾아 볼 때

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 모든 방법까지 범위 스택의 유형과 일치 뭔가 보이지 않는 것

, 그냥 중단됩니다 : 당신이이 일을하는 것처럼 그것은이다 형식이 호환되지 않습니다.

참고 :이 ... 이렇게하지 수는 자신의 정신을 보존하기 위해 단지를,의 것처럼 그것은, 그것은이 결정되었습니다하지 않는 것이는 안된다.

+0

하지만 두 개의 실행 함수에는 동일한 서명이 없습니다. 이것은 과부하입니다. 무시하지 않습니다. 분명히 –

+0

이 우선합니다. 그렇지 않은 경우 올바르게 오버로드됩니다. – Claudiu

+1

과부하가되지 않습니다. – DJClayworth

1

는 지금까지 내가 중첩 된 클래스 사이에 실행하는 방법을 선택하는 규칙을 기억으로는 약 상속 트리에서 방법을 선택하기위한 규칙과 동일합니다. 우리가 여기에 오는 것은 과부하가 아니라는 것을 의미합니다. 이들의 차이점은 상속 방법을 이해하는 데 중요합니다.

Runnable이 하위 클래스로 선언 된 경우 run() 메서드는 부모에서 run (int) 메서드를 숨 깁니다. run (...) 호출은 Runnable에서 호출을 시도하지만 서명과 일치하지 않으면 실패합니다. 자식에서 foo가 선언되지 않았으므로 부모의 자식이 호출됩니다.

동일한 원칙이 여기에서 발생합니다. "메소드 은닉"에 대한 참조를 찾으십시오.

관련 문제