Java 超类是否不调用重写的方法?

Java 超类是否不调用重写的方法?,java,oop,polymorphism,overriding,Java,Oop,Polymorphism,Overriding,我有以下课程: class foo { public void a() { print("a"); } public void b() { a(); } } class bar extends foo { public void a() { print("overwritten a"); } } 现在调用bar.b()时,我希望它调用foo中被重写的方法a()。但是,它会打印“a” 当我运行以下命

我有以下课程:

class foo {
    public void a() {
        print("a");
    }
    public void b() {
        a();
    }
}

class bar extends foo {
    public void a() {
        print("overwritten a");
    }
}

现在调用bar.b()时,我希望它调用foo中被重写的方法a()。但是,它会打印“a”

当我运行以下命令时:

public class Program {
    public static void main(String[] args) {
        bar b = new bar();
        b.b();
    }
}

class foo {
    public void a() {
       System.out.printf("a");
    }
    public void b() {
        a();
    }
}

class bar extends foo {
    public void a() {
        System.out.printf("overwritten a");
    }
}
我得到以下输出:

overwritten a

这就是我希望看到的。

这些方法是被定义为静态的吗?这是我唯一能看到的结果。我在这里找到了一个很好的解释:

可能是您试图使用静态方法,因为它们不会被重写,所以无法工作


一种很好的检查方法是将@Override注释添加到bar.A()中,并查看编译器是否会给您一个错误,即A()实际上并没有覆盖任何内容

如果您来自C#或其他语言,您可能会感到困惑,因为您必须显式声明虚拟函数和/或重写函数

在Java中,所有实例函数都是虚拟的,并且可以被重写——除非它们被声明为private和/或final

无需指定新的@Override注释即可执行此操作,添加注释只需指定您的意图是重写,如果不是重写,则会导致警告或错误。(例如,如果您意外拼错了方法名)


Andrew的示例说明了这应该如何工作。

您的两个类在不同的包中吗?您的foo类方法是声明为public、protected、private还是package local?显然,如果他们是私人的,这是行不通的。可能不太明显的是,如果它们是包本地的(即没有公共/受保护/私有作用域),那么您只能在与原始类位于同一个包中时重写它们

例如:

package original; public class Foo { void a() { System.out.println("A"); } public void b() { a(); } } package another; public class Bar extends original.Foo { void a() { System.out.println("Overwritten A"); } } package another; public class Program { public static void main(String[] args) { Bar bar = new Bar(); bar.b(); } } 包装原件; 公开课Foo{ void a(){System.out.println(“a”);} 公共无效b(){a();} } 包装另一个; 公共类栏扩展了original.Foo{ void a(){System.out.println(“覆盖a”);} } 包装另一个; 公共课程{ 公共静态void main(字符串[]args){ 条形=新条形(); bar.b(); } }
在这种情况下,您仍然会得到“A”。如果您在Foo public或protected中声明原始的a()方法,您将得到预期的结果。

来自马口铁:

“被调用的重写方法的版本是子类中的版本。被调用的隐藏方法的版本取决于它是从超类调用还是从子类调用。”


因此,如果它们都是静态方法,并且您从超类调用该方法,那么将调用超类方法,而不是子类方法。所以,实际上,没有发生重写。

当我在一个Android程序上工作时,我的Java类也遇到了同样的问题。事实证明,问题不在于类,而在于Android框架处理屏幕输出的方式

例如,如果输出是在父类的onCreate()方法中编程的,则Android无法从第一个子类以外的子类中正确获取重写方法的输出。老实说,我不明白调用订单的整个方法


为了解决这个问题,我只需在onResume()中对输出进行编程,现在它似乎工作正常

你赢了我一分钟。我得到了同样的输出。也许他在发帖方面打败了你,否则,我相信,我们在发帖之前就得到了这个输出。请原谅这个教训:它被称为“覆盖”,而不是“覆盖”。您所编写的代码应该如您所期望的那样工作-正如下面的许多答案所建议的那样,要获得您正在获得的结果,您必须在代码中执行一些您没有在此处显示的其他操作。这是我的问题;将supertype方法更改为protected修复了它。我不明白的是,为什么subtype方法上的@Override标记没有让编译器在无法工作时给我一条错误消息。