Obtener el objeto de la clase externa del objeto de la clase interna

tengo el siguiente código. Quiero obtener el objeto de clase externo con el que creé el objeto inner clase inner . ¿Cómo puedo hacerlo?

 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 :-( "); } } } 

EDITAR: Bueno, algunos de ustedes sugirieron modificar la clase interna agregando un método:

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

Pero, ¿y si no tengo control para modificar la clase interna, entonces (solo para confirmar) tenemos alguna otra forma de obtener el objeto de clase externo correspondiente del objeto de la clase interna?

Dentro de la clase interna, puedes usar OuterClass.this . Esta expresión, que permite referirse a cualquier instancia léxicamente envolvente, se describe en el JLS como Calificado .

Sin embargo, no creo que haya una manera de obtener la instancia fuera del código de la clase interna. Por supuesto, siempre puede presentar su propia propiedad:

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

EDITAR: Por experimentación, parece que el campo que contiene la referencia a la clase externa tiene acceso a nivel de paquete, al menos con el JDK que estoy usando.

EDITAR: El nombre usado ( this$0 ) es realmente válido en Java, aunque el JLS desalienta su uso:

El carácter $ debe usarse solo en código fuente generado mecánicamente o, raramente, para acceder a nombres preexistentes en sistemas heredados.

OuterClass.this referencia a la clase externa.

Podría (pero no debería) usar la reflexión para el trabajo:

 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); } } 

Por supuesto, el nombre de la referencia implícita es completamente poco fiable, así que como dije, no deberías 🙂

La respuesta más general a esta pregunta involucra variables sombreadas y cómo se accede a ellas.

En el siguiente ejemplo (de Oracle), la variable x en main () está sombreando 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(); } } 

Ejecutando este progtwig se imprimirá:

 x=0, Test.this.x=1 

Más en: http://docs.oracle.com/javase/specs/jls/se7/html/jls-6.html#jls-6.6

Creo que esto puede ser un abuso del uso de una clase interna. Me parece que lo que quieres hacer es violar los conceptos fundamentales de la progtwigción orientada a objetos. Si desea acceder a la clase externa desde la clase interna, incluya una referencia a la clase externa para que tenga acceso a ella. Cuando tienes que hacer cosas complicadas como esta, generalmente es una señal de que debes reconsiderar tus elecciones de diseño.

Aquí está el ejemplo:

 // Test public void foo() { C c = new C(); A s; s = ((AB)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"; } } 

Lo acabo de hacer así:

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

Por supuesto, debe poder modificar la clase interna y todos los que obtienen el objeto de la clase interna ahora tienen acceso al objeto de la clase externa. En mi caso, está bien.

si no tienes control para modificar la clase interna, la reflexión puede ayudarte (pero no recomendar). este $ 0 es una referencia en la clase interna que indica qué instancia de la clase externa se utilizó para crear una instancia actual de la clase interna.

 public class Outer { public Inner getInner(){ return new Inner(this,this.getClass()); } class Inner { public Inner(Outer outer, Class aClass) { System.out.println(outer); System.out.println(aClass.getName()); System.out.println(); } } public static void main(String[] args) { new Outer().getInner(); } } 
 /** * Not applicable to Static Inner Class (nested class) */ public static Object getDeclaringTopLevelClassObject(Object object) { if (object == null) { return null; } Class cls = object.getClass(); if (cls == null) { return object; } Class outerCls = cls.getEnclosingClass(); if (outerCls == null) { // this is top-level class return object; } // get outer class object Object outerObj = null; try { Field[] fields = cls.getDeclaredFields(); for (Field field : fields) { if (field != null && field.getType() == outerCls && field.getName() != null && field.getName().startsWith("this$")) { field.setAccessible(true); outerObj = field.get(object); break; } } } catch (Exception e) { e.printStackTrace(); } return getDeclaringTopLevelClassObject(outerObj); } 

Por supuesto, el nombre de la referencia implícita no es confiable, por lo que no debe usar la reflexión para el trabajo.