2 回答

TA贡献1852条经验 获得超7个赞
简而言之,经过极大的简化,内存中的对象被表示为指向包含其所有字段成员的区域(每个对象实例的唯一区域副本)和包含指向成员函数的指针的表/区域(每个类一个,相同对于所有对象)。
在 Java 中,所有函数成员都是虚拟的,因此覆盖函数成员可以覆盖虚拟方法内存表中的单元格。所以虚拟基本上意味着能够被覆盖。还有一个特殊的指针,叫做'super',它指向父类的虚方法表。所以你可以通过'super'关键字访问这个表。
如果在祖先中声明字段成员,则扩展了父对象实例区域,即内存中的所有祖先字段都在父字段之后。但是当您对两者使用相同的名称时,这会产生歧义,因此编译器警告您正在“隐藏”成员。它们没有被覆盖,作为函数,它们仍然存在,但编译器选择实际字段作为在类中声明的字段,具体取决于您使用的指针类型。如果您不指定任何指针,则 this 将隐式视为“this”,并且类型将是祖先,即祖先的字段。要访问父类字段,您需要将(this)指针强制转换为父类,因此编译器将选择您隐藏在祖先中的父类的字段。
这里的区别是因为同一个类的所有对象都使用相同的方法,但是对象实例之间不共享字段的值。

TA贡献1810条经验 获得超5个赞
您需要强制转换,因为实例字段不会被覆盖(就像方法一样)。
当您在子类中重新声明父类的字段时,您隐藏了父类的字段。
当一个字段被隐藏时,你使用父类型的引用来读取父字段的值:
因此,需要其中任何一个来读取以下字段Grand:
((Grand)this).x
要么:
Grand grand = this
int val = grand.x //reads parent's x
这有希望表明隐藏字段是一个坏主意。
添加回答
举报