2016-06-29 68 views
0

在下面的代碼,我發現我可以調用getWorld(),而不到HelloWorld對象的引用?但隱式'this'關鍵字現在是否指向內部匿名類?如果是這樣,爲什麼我能夠調用getWorld()?隱式「this」在匿名類中引用了什麼?

public class HelloWorld { 
    public void getWorld() { 
     this.setListener(new MyListenerInterface(){ 
      @Override 
      public void innerMethod() { 
       getWorld(); 
      } 
     }); 
    } 
} 

忽略代碼中的遞歸。

回答

2

答案是Section 15.12 of the JLS

如果它是一個簡單的名字,也就是一個標識符,那麼方法的名稱就是標識符。

如果出現具有該名稱的可見方法聲明的範圍內的標識符(§6.3,§6.4.1),則:

  • 如果有一個封閉類型聲明其中該方法是一成員,讓T成爲最內層的類型聲明。類或接口進行搜索是T.

僅僅通過使用該方法的簡單名稱,來調用哪個方法分辨率查找通過封閉的方法,直到找到一個具有方法與名稱,然後嘗試使用該方法(或多個方法)來查找完全匹配。

這與使用this.getWorld()的情況不同,因爲this明確指向內部類實例。這會導致不同類型的分辨率(規範中的Typename . Identifier部分,僅在鏈接引號的下面),它不會查看封閉的外部類。

這方面的一個有趣的結果是,你可能會導致代碼停止通過添加一個方法到具有相同名稱的內部類編譯,但不同的元數。由於它只是在嘗試確定類實例來解析它時才搜索名稱本身,它將嘗試使用內部類,但找不到完全匹配的方法。

所以這個:

public class HelloWorld { 
    public void getWorld() { 
     this.setListener(new MyListenerInterface(){ 
      @Override 
      public void innerMethod() { 
       getWorld(); 
      } 
      void getWorld(int i){} 
     }); 
    } 
} 

不會編譯。方法名稱解析將在內部類中發現getWorld,因此將停止搜索層次結構。但是,當它嘗試執行arity解析時,它將看到類中的(一個)getWorld方法都不匹配,並且會失敗。

TL; DR - 僅使用簡單的名稱是注意不太一樣使用,即使它通常計算爲同樣的事情。語言規範具有處理這種情況的特定規則,這可以允許它查看任何封閉的實例以找到匹配的方法。

1

調用getWorld您在匿名類之外返回頂級類,因此this引用了創建匿名類的對象。

這就像調用其他類的方法,this那裏引用了一個不同的對象(不是調用者,而是被調用者)。

+0

我覺得他問的是Java語言本身的運作。你說得對,這就是它在做什麼,但爲什麼? – jiveturkey

相關問題