una obtener objetos objeto misma metodos metodo llamar instanciar herencia ejemplos crear como clases clase atributos java inner-classes

obtener - objetos en java



Conseguir el objeto de clase exterior del objeto de clase interior (9)

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

tengo el siguiente código. Quiero obtener el objeto de la clase externa mediante el cual creé el objeto de la 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 ¿qué pasa si no tengo el control para modificar la clase interna, entonces (solo para confirmar) tenemos otra forma de obtener el objeto de la clase externa correspondiente del objeto de la clase interna?


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

Sin embargo, no creo que haya una manera de obtener la instancia desde fuera del código de la clase interna. Por supuesto, siempre puedes introducir tu propia propiedad:

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

EDITAR: según 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.

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

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


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

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


Podrías (pero no deberías) 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 absolutamente poco confiable, así que como dije, no deberías :-)


Si no tiene control para modificar la clase interna, la respuesta puede ayudarlo (pero no recomendar). este $ 0 es una referencia en la clase interna que indica qué instancia de la clase externa se usó para crear la instancia actual de la clase interna.


Simplemente lo hice 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 tienen acceso al objeto de la clase externa ahora. En mi caso está bien.


OuterClass.this referencia a la clase externa.


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


public class Outer { public Inner getInner(){ return new Inner(this,this.getClass()); } class Inner { public Inner(Outer outer, Class<? extends Outer> aClass) { System.out.println(outer); System.out.println(aClass.getName()); System.out.println(); } } public static void main(String[] args) { new Outer().getInner(); } }