为什么在覆盖该方法时调用超类方法? (来自OCA练习测试)
Why is superclass method called while that method is overriden? (from OCA practice test)
来自these OCA practice questions (pdf)中的第三题:
abstract class Writer {
public static void write() {
System.out.println("Writing...");
}
}
class Author extends Writer {
public static void write() {
System.out.println("Writing book");
}
}
public class Programmer extends Writer {
public static void write() {
System.out.println("Writing code");
}
public static void main(String[] args) {
Writer w = new Programmer();
w.write();
}
}
输出为Writing...
。
我不明白为什么。由于 Programmer
覆盖了 Writer
的 write 方法,我认为它应该调用 Programmer
中的方法而不是 Writer
中的方法。
为什么?
这里你要明白两点。
如果有 static
个成员,则没有压倒一切的概念。它们只是 static
并且永远不会根据实例改变。
和 static
成员绑定到 class 而不是实例。因此,无论实例是什么,它们都会查看调用并执行的类型。
引用的类型是Writer
。您调用了一个未应用覆盖的静态方法 - 来自 Writer
的方法将被调用。
该机制称为 method hiding。
查看这些案例:
new Programmer().write(); // code [Programmer]
((Writer)new Author()).write(); // ... [Writer]
new Author().write(); // book [Author]
((Writer)new Programmer()).write(); // ... [Writer]
new Writer() {{}}.write(); // ... [Writer]
自己找到了答案。
Java 中没有覆盖静态方法这样的事情。这就是为什么当你从超类引用调用静态方法时,超类静态方法将被调用。
所以
public class SuperClass {
public static void write() {
System.out.println("Writing Super");
}
public void writeMore() {
System.out.println("super something");
}
}
public class SubClass extends SuperClass {
public static void write() {
System.out.println("Writing Sub");
}
public void writeMore() {
System.out.println("sub something");
}
}
public class Test {
public static void main(String[] args) {
SuperClass super = new SubClass();
super.write();
super.writeMore();
}
}
会输出
Writing super
sub something
如果你想从子类中调用静态write()方法。您必须从子类中引用它。例如:
SubClass sub = new Subclass();
sub.write();
我从中了解到的一些来源:
https://www.geeksforgeeks.org/can-we-overload-or-override-static-methods-in-java/
Why doesn't Java allow overriding of static methods?
众所周知,static
方法不能被覆盖。如果我们尝试这样做,结果却是方法隐藏。在上面的例子中,class- Writer
和 Programmer
都包含 write()
方法。
当 Programmer
扩展 Writer
class 并提供其自己的 write()
方法实现时,它只是隐藏了它的 Writer
实现。
现在,在运行时,编译器只检查引用类型(因为它是静态方法,编译器不关心为调用该方法而创建的对象。记住,静态方法是 class 方法) .因此,编译器检查并发现引用 w
是类型 Writer
,它调用 write
方法的 Writer
版本。
如果这些方法不是 static
,那么您期望的将是输出。
来自these OCA practice questions (pdf)中的第三题:
abstract class Writer {
public static void write() {
System.out.println("Writing...");
}
}
class Author extends Writer {
public static void write() {
System.out.println("Writing book");
}
}
public class Programmer extends Writer {
public static void write() {
System.out.println("Writing code");
}
public static void main(String[] args) {
Writer w = new Programmer();
w.write();
}
}
输出为Writing...
。
我不明白为什么。由于 Programmer
覆盖了 Writer
的 write 方法,我认为它应该调用 Programmer
中的方法而不是 Writer
中的方法。
为什么?
这里你要明白两点。
如果有 static
个成员,则没有压倒一切的概念。它们只是 static
并且永远不会根据实例改变。
和 static
成员绑定到 class 而不是实例。因此,无论实例是什么,它们都会查看调用并执行的类型。
引用的类型是Writer
。您调用了一个未应用覆盖的静态方法 - 来自 Writer
的方法将被调用。
该机制称为 method hiding。
查看这些案例:
new Programmer().write(); // code [Programmer]
((Writer)new Author()).write(); // ... [Writer]
new Author().write(); // book [Author]
((Writer)new Programmer()).write(); // ... [Writer]
new Writer() {{}}.write(); // ... [Writer]
自己找到了答案。
Java 中没有覆盖静态方法这样的事情。这就是为什么当你从超类引用调用静态方法时,超类静态方法将被调用。
所以
public class SuperClass {
public static void write() {
System.out.println("Writing Super");
}
public void writeMore() {
System.out.println("super something");
}
}
public class SubClass extends SuperClass {
public static void write() {
System.out.println("Writing Sub");
}
public void writeMore() {
System.out.println("sub something");
}
}
public class Test {
public static void main(String[] args) {
SuperClass super = new SubClass();
super.write();
super.writeMore();
}
}
会输出
Writing super
sub something
如果你想从子类中调用静态write()方法。您必须从子类中引用它。例如:
SubClass sub = new Subclass();
sub.write();
我从中了解到的一些来源: https://www.geeksforgeeks.org/can-we-overload-or-override-static-methods-in-java/ Why doesn't Java allow overriding of static methods?
众所周知,static
方法不能被覆盖。如果我们尝试这样做,结果却是方法隐藏。在上面的例子中,class- Writer
和 Programmer
都包含 write()
方法。
当 Programmer
扩展 Writer
class 并提供其自己的 write()
方法实现时,它只是隐藏了它的 Writer
实现。
现在,在运行时,编译器只检查引用类型(因为它是静态方法,编译器不关心为调用该方法而创建的对象。记住,静态方法是 class 方法) .因此,编译器检查并发现引用 w
是类型 Writer
,它调用 write
方法的 Writer
版本。
如果这些方法不是 static
,那么您期望的将是输出。