2009-11-29 15 views
177

Tengo el siguiente código. Quiero obtener el objeto de clase externo con el que creé el objeto de clase interna inner. ¿Cómo puedo hacerlo?Obtención del objeto de clase externa desde el objeto de clase interna

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

EDIT: Bueno, algunos de ustedes sugirió la modificación de la clase interna mediante la adición de un método:

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

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

Respuesta

250

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

Yo no creo que hay una manera de obtener la instancia desde fuera del código de la clase interna. Por supuesto, siempre se puede introducir a su propia propiedad:

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

EDIT: Por la 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.

EDIT: El nombre utilizado (this$0) es realmente válida en Java, aunque el JLS desalienta su uso:

El carácter $ debe utilizarse sólo en código fuente generado de forma mecánica o, raramente , para acceder a nombres preexistentes en sistemas heredados.

+0

Gracias Jon! Pero, ¿qué pasa si no tengo control para modificar la clase interna (verifique mi edición). – peakit

+5

@peakit: Entonces, que yo sepa, no tienes suerte a menos que uses el reflejo. Sin embargo, se siente como si fuera una violación de la encapsulación; si la clase interna no quiere decirle cuál es su instancia externa, debe respetar eso e intentar diseñarlo de forma tal que no lo necesite. –

+0

¿Esto todavía es válido en Java 8? – misty

24

OuterClass.this hace referencia a la clase externa.

+4

Pero solo en/dentro de la fuente de OuterClass. Y no creo que eso es lo que quiere el OP. –

0

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 programació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.

17

Usted podría (pero no debe) utilizar 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 totalmente fiable, por lo que como he dicho, no debe: -)

0

Aquí está el ejemplo:

// 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

sólo lo hice así:

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

Por supuesto, necesita 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.

0

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

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

La ejecución de este programa imprimirá:

x=0, Test.this.x=1 

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

0

si no tiene control para modificar la clase interna, la reflexión puede ayudarlo (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.

Cuestiones relacionadas