2013-02-08 43 views
0

假設我有一個Outer類。可以說有一個非靜態成員類Inner。因此,如果Outer類聲明類型爲Inner的字段並且按照定義,則Outer實例將引用Inner的實例。但是Inner實例如何也有一個隱含參考Outer?這個關聯何時創建?隱式引用Java中的封閉類

+4

「因此,一個外部實例始終具有內在的實例的引用,這是由定義。」 - 這不是真的。 – millimoose 2013-02-08 17:14:32

+0

@millimoose爲什麼不是真的? – Geek 2013-02-08 17:15:31

+2

如果外部類爲其明確聲明瞭一個字段,那麼外部類的實例將僅保存對內部類實例的引用。 – Alex 2013-02-08 17:18:50

回答

2

Java language Spec

一類的O的直接內類C的我一個實例爲O的一個實例,被稱爲 立即封閉實例1相關的 。對象的立即封閉實例(如果有的話)是 ,在創建對象時(第15.9.2節)確定。

0

代碼

class Outer { 

    class Inner { 
     void printOuterThis() { 
      System.out.println(Outer.this); 
     } 
    } 

} 

Outer.Inner oi = new Outer().new Inner(); 

大多是等效於這樣的:

class Outer { 

    static class Inner { 
     Outer outerThis; 

     public Inner(Outer outerThis) { 
      this.outerThis = outerThis; 
     } 

     void printOuterThis() { 
      System.out.println(outerThis); 
     } 
    } 
} 

public class Scratch { 
    public static void main(String[] args) { 
     Outer.Inner oi = new Outer.Inner(new Outer()); 
    } 
} 

編譯器自動發出代碼,不會在第二發生的情況:其保持的值的字段(this$0Outer.this)用於隱式引用,並轉換Inner的所有構造函數,並調用它們以添加此字段的初始化。

+1

但是,您實際上無法編譯第二個示例嗎? – Alex 2013-02-08 17:27:18

+0

@Alex有一堆錯誤,我從內存中寫入它。現在應該沒問題。 – millimoose 2013-02-08 17:30:26

+0

對,我改變了第二個示例以匹配反編譯器告訴我的確實發生的事情。 – millimoose 2013-02-08 17:35:37

1

你有它周圍的其他方法:

public class Outer { 

    void foo() { 
     // In this Outer method, we have no implicit instance of Inner. 
     innerbar(); // Compiler error: The method bar() is undefined for the type Outer 
     Inner.this.innerbar();// Compiler error: No enclosing instance of the type Outer.Inner is accessible in scope 

     // instead, one has to create explicitly instance of Inner: 

     Inner inner1 = new Inner(); 
     Inner inner2 = new Inner(); 

     inner1.innerbar(); // fine! 
    } 


    class Inner { 
     void innerbar() {}; 

     void callOuter() { 
      // But Inner has an implicit reference to Outer. 
      callMe(); 
      // it works also through Outer.this 
      Outer.this.callMe(); 
     } 
    } 

    void callMe() {} 

}