[英]Why does line 4 only print out "B move"?
我试图理解这段代码的输出。 我了解除第 4 行以外的其他输出。
代码:
class A{
public void move(Object o){
System.out.println("A move");
}
public void keep(String s){
System.out.println("A keep");
}
}
class B extends A{
public void move(Object o){
System.out.println("B move");
}
public void keep(Object o){
System.out.println("B keep");
}
}
class C extends B{
public void move(String s){
super.move(s);
System.out.println("C move");
}
public void keep(String s){
super.keep(s);
System.out.println("C keep");
}
}
public class main {
public static void main(String[] args) {
A a = new A();
A b = new B();
A c = new C();
a.move("Test"); //line1
b.move("Test"); //line2
b.keep("Test"); //line3
c.move("Test"); //line4
c.keep("Test"); //line5
}
}
output:
A move
B move
A keep
B move
A keep
C keep
我期待第 4 行打印出“B move.C move”,但它只是在“B move”处结束。 我认为它与第 5 行具有相同的逻辑。有人知道发生了什么吗?
重载由编译器决定,覆盖在运行时完成。 一个方法的“身份”包括它的参数类型和它的返回类型以及它的名字。 所以:
因此,编译器在第 4 行看到c.move("Test")
,并确定这是对A
类型表达式的调用(因为您将变量c
声明为A c;
。看看 A 必须做什么报价,只有一个名为move
的方法,其签名为void move(Object)
。因此它在 class 文件中被编码:调用A.move(Object)
。
然后在运行时,运行时检查void move(Object)
方法在c
变量指向的 object 的实际类型上的最具体实现,实际上是 C 类型的C
。 move(Object) 最具体的实现在 B 中:B 有一个void move(Object)
实现。 C 有一个void move(String)
,但这不算“计数”——它没有相同的身份,实际上,它有一个不同的名字,与 A 的 move(Object) 没有任何关系——它们有相同的实际方法名称 ( move
) 是巧合。
两个提示:
@Override
注释。 如果您在此处这样做,编译器会告诉您例如 B 的keep(Object o)
方法不是重写,如果您将其标记为@Override
,它还会将 C 的 move 方法标记为错误。 (此注释并不意味着“此方法是重写”。它的意思是:如果此方法未重写或实现任何内容,则会生成编译时错误。其完整签名与父类型中的方法匹配的方法仍然会重写它,即使没有注释。它只是经过编译器检查的文档,这是您应该使用的好东西)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.