最近我使用main
方法使用一些简单的Java代码来快速测试我编写的代码。我最终遇到了两个类似的类:
public class A {
public static void main(String[] args) {
// code here
}
}
public class B extends A {
public static void main(String[] args) throws IOException {
// code here
}
}
我很惊讶代码停止编译,Eclipse抱怨Exception IOException is not compatible with throws clause in A.main(String[])
。
嗯,这两种方法都是静态的,而main
中的B
函数只是隐藏A
中的一个,所以我认为它们之间完全没有关系。在静态方法中,我们没有多态,并且在编译期间调用绑定到具体的方法实现,因此我无法理解为什么main
中的B
不能抛出未在main
中声明的异常A
中的签名。
为什么Java设计者决定强制执行这样的约束,如果编译器没有强制执行约束,它会在什么情况下导致问题?
答案 0 :(得分:2)
我从来没有意识到这个事实,但在准确分析之后,我认为没有理由为什么编译器应该强制执行这样的约束。尽管如此,匹配main
方法时不会出现不一致,因为静态方法的链接也是静态的。在这种情况下,不允许覆盖。
答案 1 :(得分:1)
关键是我们正在讨论静态方法,它们确实不应受多态性的影响。但是,在我看来静态方法属于一个Class对象,就像任何其他对象应该服从多态,对吗?
答案 2 :(得分:-3)
'extends'关键字表示在声明B类时继承A类中的方法。由于A类是B类的父类,所以主方法的声明仍然在A类中,尽管你是正在B类重新定义它。
当您处理静态方法时,父类方法不会被子类覆盖,只是隐藏它。
http://docs.oracle.com/javase/tutorial/java/IandI/override.html
可以提供更多细节,但这里有一段摘录:
隐藏静态方法和覆盖实例方法之间的区别具有重要意义:
被调用的重写实例方法的版本是 一个在子类中。得到的隐藏静态方法的版本 调用取决于它是从超类调用还是调用 子类。
原始答案
编译器强制使用此约束来帮助简化更复杂层次结构中的继承。
以toString()方法为例。它由Java中的每个对象继承,假设您能够覆盖此方法的声明以允许子类抛出不同的异常。在处理所有这些潜在的新例外方面,这是一个灾难的处方。
TLDR-编译器强制您遵守父类函数定义,以便其他程序员可以在晚上睡觉。