2009-11-29 111 views
177

我有以下代码。我想要获得使用其创建内部类对象inner的外部类对象。我该怎么做?从内部类对象中获取外部类对象

public class OuterClass { 

    public class InnerClass { 
     private String name = "Peakit"; 
    } 

    public static void main(String[] args) { 
     OuterClass outer = new OuterClass(); 
     InnerClass inner = outer.new InnerClass(); 
     // How to get the same outer object which created the inner object back? 
     OuterClass anotherOuter = ?? ; 

     if(anotherOuter == outer) { 
      System.out.println("Was able to reach out to the outer object via inner !!"); 
     } else { 
      System.out.println("No luck :-("); 
     } 
    } 
} 

编辑:嗯,有些你们的建议修改内部类的加入方法:

public OuterClass outer() { 
    return OuterClass.this; 
} 

但是,如果我没有控制修改内部类的东西,然后(只是为了确认)我们是否有其他方法从内部类对象中获取相应的外部类对象?

回答

250

在内部类本身,你可以使用OuterClass.this。该表达式允许引用任何词汇封闭的实例,在JLS中描述为Qualified this

我不是认为有一种方法可以从内部类的代码之外获取实例。当然,你总是可以介绍一下你自己的财产:

public OuterClass getOuter() { 
    return OuterClass.this; 
} 

编辑:通过实验,它看起来像场抱着参考外部类已经包级别的访问权限 - 至少在我使用的是JDK。

编辑:使用的名称(this$0在Java中实际上是有效的,虽然JLS阻碍其使用:

$字符应当仅 机械产生的源代码或, 很少使用,以访问原有系统上已存在的名称。

+0

谢谢乔恩!但是如果我没有控制权来修改内部类(如何检查我的编辑)呢? – peakit 2009-11-29 19:22:51

+5

@peakit:据我所知,除非你使用反射,否则你运气不好。它觉得它实际上是封装的违反 - 如果内部类不想告诉你它的外部实例是什么,那么你应该尊重它并尝试设计,以至于你不需要它。 – 2009-11-29 19:29:08

+0

这在Java 8中仍然有效吗? – misty 2016-09-28 16:45:43

24

OuterClass.this引用外部类。

+4

但只在/在OuterClass的源内。我不认为这是OP想要的。 – 2010-02-02 09:18:05

0

我认为这可能是滥用内部类的使用。在我看来,你想要做的就是违反面向对象编程的基本概念。如果您想从内部类访问外部类,请包含对外部类的引用,以便您可以访问它。当你必须做这样棘手的事情时,它通常表明你应该重新考虑你的设计选择。

17

你可以(但你不应该)使用反射作业:

import java.lang.reflect.Field; 

public class Outer { 
    public class Inner { 
    } 

    public static void main(String[] args) throws Exception { 

     // Create the inner instance 
     Inner inner = new Outer().new Inner(); 

     // Get the implicit reference from the inner to the outer instance 
     // ... make it accessible, as it has default visibility 
     Field field = Inner.class.getDeclaredField("this$0"); 
     field.setAccessible(true); 

     // Dereference and cast it 
     Outer outer = (Outer) field.get(inner); 
     System.out.println(outer); 
    } 
} 

当然,隐式引用的名称是完全不可靠的,所以我说,你不应该: - )

0

这里的例子:

// Test 
public void foo() { 
    C c = new C(); 
    A s; 
    s = ((A.B)c).get(); 
    System.out.println(s.getR()); 
} 

// classes 
class C {} 

class A { 
    public class B extends C{ 
    A get() {return A.this;} 
    } 
    public String getR() { 
    return "This is string"; 
    } 
} 
0

我只是做了这样的:

public class CherryTree { 
    public class Cherry { 
     public final CherryTree cherryTree = CherryTree.this; 
     // [...] 
    } 
    // [...] 
} 

当然,你需要能够修改内部类,每个获得内部类对象的人现在都可以访问外部类对象。在我的情况下,这很好。

0

更普遍的回答这个问题涉及阴影变量以及它们是如何访问。

在下面的例子(从Oracle),在主可变X()被遮蔽Test.x

class Test { 
    static int x = 1; 
    public static void main(String[] args) { 
     InnerClass innerClassInstance = new InnerClass() 
     { 
      public void printX() 
      { 
       System.out.print("x=" + x); 
       System.out.println(", Test.this.x=" + Test.this.x); 
      } 
     } 
     innerClassInstance.printX(); 
    } 

    public abstract static class InnerClass 
    { 
     int x = 0; 

     public InnerClass() { } 

     public abstract void printX(); 
    } 
} 

运行此程序将打印:

x=0, Test.this.x=1 

更多于:http://docs.oracle.com/javase/specs/jls/se7/html/jls-6.html#jls-6.6

0

如果您没有控制权来修改内部类,则反馈可能对您有帮助(但不推荐)。这个$ 0是Inner类中的引用,它告诉哪个Outer类的实例被用来创建Inner类的当前实例。