考虑具有内部类和继承的这种情况:
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
}
}
}
类B
的内存布局如何?它是否有两个外部this
引用,它们都指向同一个对象?或者它只有一个外this
引用。这个参考的类型是什么?
我之所以问:我有一个或多或少的深层次结构,它使用这样的嵌套类。如果为每个继承级别复制了外部this
引用,那么我应该考虑一下这个设计。
此外,我只是对Java编程语言的设计细节感到好奇。
我使用javap
来检查布局:this
指针真的被复制了
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();
}
答案 0 :(得分:2)
您可以使用javap
查找班级中的哪些字段。 (这取决于编译器,而不是JVM。)在这种情况下:
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();
}
正如您所看到的,有一个对Y
的封闭实例的引用 - 但X$A
也会引用X
的封闭实例(您可以使用javap -p X$A
如果你愿意的话)。所以是的,该对象总共有两个字段用于封闭实例。
您可以使用javap -c Y$B
查看构造函数的主体,这表明封闭的Y
实例引用随后会传递给X.A
的构造函数作为封闭{{1}实例引用 - 确认两个字段具有相同的值。
但是,我还没有找到解决JLS的问题。就其本身而言,这是一个值得关注的问题 - 如果你处于一个很难用JLS解释的情况,这是一个很好的暗示,其他开发人员可能无法跟踪正在发生的事情。这对我来说感觉就像一个错综复杂的设计...除非你真的需要所有这些嵌套类,否则我会尽量避免它们。
答案 1 :(得分:1)
我认为继承层次结构中的每个内部类都有它自己的“外部this”引用,因为B可以有一个像
这样的构造函数 public B(X a) {
a.super();
}
这样你就可以了
X x = new X();
Y y = new Y();
Y.B b = y.new B(x);
现在你有一个Y.B的实例,其中foo()方法返回y,但A中的原始foo方法返回x!