Java inner classes and inheritance: is there a duplicate xref?

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

      

What does the layout of the class look like B

? Does it have two xrefs this

that point to the same object? Or it only has one external link this

. What is the type of this link?

The reason I'm asking is: I have a more or less deep hierarchy that uses nested classes. If the xref has this

been replicated for each inheritance level, then I should think about this construct.

Also, I'm just curious about this design detail of the Java programming language.


I used javap

to check the layout: the pointer is this

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

      

+3


source to share


2 answers


You can use javap

to find out what fields a class has. (This depends on 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, one link to the enclosing instance Y

is - but X$A

will also contain a link to the attached instance X

(which you can check with javap -p X$A

if you like). So yes, the object will have two fields to include instances.



You can use javap -c Y$B

to view the body of the constructor, which shows that the attached instance of the instance is Y

then passed to the constructor X.A

as an instance reference X

, confirming that the two fields will have the same value.

However, I have not yet discovered where in the JLS this is addressed. This in itself is a concern - if you're in a situation that is difficult to explain with the JLS, it's a pretty good hint that other developers won't be able to keep track of what's going on. This seems like a confusing design to me ... if you don't really need all these nested classes, I would try to avoid them.

+2


source


I think that every inner class in the inheritance hierarchy has its own "outer this" reference, because B can have a constructor like

    public B(X a) {
        a.super();
    }

      

So you can do



X x = new X();
Y y = new Y();
Y.B b = y.new B(x);

      

You now have an instance of YB, where the foo () method returns y, but the original foo method returns x!

+1


source







All Articles