2013-02-08 85 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() {} 

}