Java中的继承:为什么强制转换变量访问的解析方式与强制转换方法调用的解析方式不同

Java中的继承:为什么强制转换变量访问的解析方式与强制转换方法调用的解析方式不同,java,inheritance,methods,casting,overloading,Java,Inheritance,Methods,Casting,Overloading,当涉及到强制转换时,继承是如何工作的(在Java中)?Casting与实例变量一样工作,但与方法不同 给定以下代码;类C中的注释指的是编译器完成的解析,可以通过查看字节码来检查 A类{ 字符串名; void test1(){ System.out.println(“ATest1=“+this”); } void test2(){ System.out.println(“ATest2=“+this”); } } B类扩展了A类{ 字符串名; void test1(){ System.out.pri

当涉及到强制转换时,继承是如何工作的(在Java中)?Casting与实例变量一样工作,但与方法不同

给定以下代码;类
C
中的注释指的是编译器完成的解析,可以通过查看字节码来检查

A类{
字符串名;
void test1(){
System.out.println(“ATest1=“+this”);
}
void test2(){
System.out.println(“ATest2=“+this”);
}
}
B类扩展了A类{
字符串名;
void test1(){
System.out.println(“BTest1=“+this”);
}
void test3(){
System.out.println(“BTest3=“+this”);
}
}
C类{
静态公共void main(字符串…参数){
B=新的B();
b、 name=“Peter”//字段b.name
((A)b).name=“Petra”//字段A.name
System.out.println(b.name);
System.out.println(((A)b).name);
b、 test1();//方法b.test1(b)
((A)b.test1();//方法A.test1(b)
b、 test3();//方法b.test3(b)
b、 test2();//方法b.test2(b)
}
}
您可以使用casting在实例
b
中设置
name
,并在其附带的“虚拟”对象(可以说是类
A
的实例)中设置
name

但是,如果涉及方法,则调用总是解析为类
b
中的实例
b
调用
test1
。尽管在
((A)b)中调用了.test1()
方法
A.test1(b)
(从JVM的角度来看)

我不懂语义。你能帮忙吗


我的猜测是
((A)b).test1()
确认类
A
中存在方法
test1
。尽管如此,类
B
在调用方法时是方法解析的起点,因为
((A)B).getClass()==>类B
。但为什么选角被“忽略”?您是否有指向Java语言规范的指针?我不知道去哪里找。

您可能会被两个名为
name
的变量弄糊涂。您应该删除
字符串名称从类
B
,然后您将获得正确的行为。在任何情况下,强制转换都“应该”被忽略——这就是方法重写的全部要点。Java中没有继承或重写像
name
这样的字段。这是两个不同的变量,它们共享相同的名称。在Java语言中,对于类
B
,您可以使用
super
访问变量,例如
super.name=Petra
this.name=Peter
。您有两个实例变量(字段),都命名为
name
。您只有一个名为
test1
的方法。在类
B
中重写了相同的方法。因此,无论您是否强制转换,都会调用相同的方法。阅读如何调用虚拟方法(Java中的方法是虚拟的);非常感谢你的推荐。但答案并不像我希望的那样具体。通过对字节码的研究,我们发现铸造的结果与预期一致。看起来这是造成意外行为的原因;我需要对此进行研究。的JVM规范在第3段的“描述”下说,该方法是针对invokevirtual的参数类选择的,在我的示例类
B
的实例
B
中。
((A)b).test1()
中的强制转换要求方法
test1()
在编译时存在,但在运行时未选择该方法。这就是我恼火的地方。感谢您的支持。您可能会对名为
name
的两个变量感到困惑。您应该删除
字符串名称从类
B
,然后您将获得正确的行为。在任何情况下,强制转换都“应该”被忽略——这就是方法重写的全部要点。Java中没有继承或重写像
name
这样的字段。这是两个不同的变量,它们共享相同的名称。在Java语言中,对于类
B
,您可以使用
super
访问变量,例如
super.name=Petra
this.name=Peter
。您有两个实例变量(字段),都命名为
name
。您只有一个名为
test1
的方法。在类
B
中重写了相同的方法。因此,无论您是否强制转换,都会调用相同的方法。阅读如何调用虚拟方法(Java中的方法是虚拟的);非常感谢你的推荐。但答案并不像我希望的那样具体。通过对字节码的研究,我们发现铸造的结果与预期一致。看起来这是造成意外行为的原因;我需要对此进行研究。的JVM规范在第3段的“描述”下说,该方法是针对invokevirtual的参数类选择的,在我的示例类
B
的实例
B
中。
((A)b).test1()
中的强制转换要求方法
test1()
在编译时存在,但在运行时未选择该方法。这就是我恼火的地方。谢谢你的支持。