Getting hold of the outer class object from the inner class object
I have the following code. I want to get hold of the outer class object using which I created the inner class object inner
. How can I do it?
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: Well, some of you guys suggested of modifying the inner class by adding a method:
public OuterClass outer() {
return OuterClass.this;
}
But what if I don't have control to modify the inner class, then (just to confirm) do we have some other way of getting the corresponding outer class object from the inner class object?
Solution 1:
Within the inner class itself, you can use OuterClass.this
. This expression, which allows to refer to any lexically enclosing instance, is described in the JLS as Qualified this
.
I don't think there's a way to get the instance from outside the code of the inner class though. Of course, you can always introduce your own property:
public OuterClass getOuter() {
return OuterClass.this;
}
EDIT: By experimentation, it looks like the field holding the reference to the outer class has package level access - at least with the JDK I'm using.
EDIT: The name used (this$0
) is actually valid in Java, although the JLS discourages its use:
The
$
character should be used only in mechanically generated source code or, rarely, to access pre-existing names on legacy systems.
Solution 2:
OuterClass.this
references the outer class.
Solution 3:
You could (but you shouldn't) use reflection for the job:
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);
}
}
Of course, the name of the implicit reference is utterly unreliable, so as I said, you shouldn't :-)
Solution 4:
The more general answer to this question involves shadowed variables and how they are accessed.
In the following example (from Oracle), the variable x in main() is 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();
}
}
Running this program will print:
x=0, Test.this.x=1
More at: http://docs.oracle.com/javase/specs/jls/se7/html/jls-6.html#jls-6.6