繁体   English   中英

为什么第 4 行只打印出“B move”?

[英]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 行具有相同的逻辑。有人知道发生了什么吗?

重载由编译器决定,覆盖在运行时完成。 一个方法的“身份”包括它的参数类型和它的返回类型以及它的名字。 所以:

  • B.keep不会覆盖 A.keep,但 B.move覆盖 A.move。
  • C.move不会覆盖 B.move/A.move。 C.keep 覆盖 A.keep 但不覆盖 B.keep。

因此,编译器在第 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM