Consider this scenario with inner classes and inheritance:
class X{
class A{
X foo(){
return X.this; // outer this reference to X returned
}
}
}
class Y extends X{
class B extends A {
Y foo(){
return Y.this; // outer this reference to Y returned
}
}
}
How does the memory layout of class B
look like? Does it have two outer this
references which both point to the same object? Or does it have only one outer this
reference. What is the type of this reference?
The reason why I ask: I have a more or less deep hierarchy that uses nested classes like this. If the outer this
reference was replicated for each level of inheritance, then I should maybe think over this design.
In addition, I am just curious about this design detail of the Java programming language.
I used javap
to check the layout: The this
pointer is really replicated
class X$A {
final X this$0; // <-- first reference
X$A(X);
X foo();
}
class Y$B extends X$A {
final Y this$0; // <-- second reference
Y$B(Y);
Y foo();
X foo();
}
You can use javap
to find out what fields a class has. (This is up to the compiler, not the JVM.) In this case:
C:\Users\Jon\Test>javap -p Y$B
Compiled from "Test.java"
class Y$B extends X$A {
final Y this$0;
Y$B(Y);
Y foo();
X foo();
}
So as you can see, there's one reference to an enclosing instance of Y
- but X$A
will also have a reference to the enclosing instance of X
(which you can verify with javap -p X$A
if you want). So yes, the object will have two fields in total for enclosing instances.
You can use javap -c Y$B
to see the body of the constructor, which shows that the enclosing Y
instance reference is then passed up to the constructor of X.A
as the enclosing X
instance reference - confirming that the two fields will have the same value.
However, I haven't yet found out where in the JLS this is addressed. In itself, this is a cause for concern - if you're in a situation which is hard to explain with the JLS, that's a pretty good hint that other developers may not be able to follow what's going on either. This feels like a convoluted design to me... unless you really need all these nested classes, I'd try to avoid them.
See more on this question at Stackoverflow