2009-11-29 146 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類的當前實例。

相關問題