public class OuterThis {
private String me = "OuterThis";
public class Inner1 {
private String me = "Inner1";
public class Inner2{
public void getEnclosingClasses() {
System.out.println(Inner1.this.me);
System.out.println(OuterThis.this.me);
}
}
}
public static void main(String[] args) {
OuterThis.Inner1.Inner2 in2 = new OuterThis().new Inner1().new Inner2();
in2.getEnclosingClasses();
}
}
You can also get the outer class reference through reflection. The this reference is encoded as this$n where n is an int specifying the level of the class. In the example above, this$0 is the outer class "OuterThis" while this$1 refers to "Inner1". So in the code above just do the following to get the enclosing class "Inner1" through reflection in the method getEnclosingClasses().
Inner1 in1 = (Inner1)getClass().getDeclaredField("this$1").get(this);
Reflection to obtain the outer class reference is usually used when you are outside the inner class. The following example illustrates it.
import java.util.ArrayList;
public class ExposeThis {
private String exposeThis = "Just Expose This";
public static void main(String[] args) throws
IllegalArgumentException, SecurityException, NoSuchFieldException,
IllegalAccessException {
Client cl = new Client();
new ExposeThis().registerMe(cl);
cl.printThis();
}
public void registerMe(Client client) {
client.addListener(new ClientListener(){});
}
public String toString() {
return exposeThis;
}
}
interface ClientListener {
}
class Client {
private ArrayList<ClientListener> clients = new ArrayList<ClientListener>();
public void addListener(ClientListener cl) {
clients.add(cl);
}
public void printThis() throws
NoSuchFieldException, IllegalArgumentException,
SecurityException, IllegalAccessException{
for (ClientListener cl: clients) {
//Get handle to OuterClass this by reflection
ExposeThis et =
(ExposeThis)cl.getClass().getDeclaredField("this$0").get(cl);
System.out.println(et);
}
}
}
Note:
Since it is possible to obtain references to enclosing classes by getting a handle to the inner class, one has to be very careful while working with inner classes.
this$0 naming is not guaranteed by the spec.
ReplyDelete