最近我使用一些简单的Java代码来使用main快速测试我编写的代码的方法.我最终遇到了两个类似的类:
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
}
}
Run Code Online (Sandbox Code Playgroud)
我很惊讶代码停止编译,Eclipse抱怨说Exception IOException is not compatible with throws clause in A.main(String[]).
好吧,这两个方法都是静态的,而main函数B只是隐藏了一个A,所以我认为它们之间完全没有关系.在静态方法我们没有多态性与呼叫被绑定到编译过程中的具体方法的实现,因此我不明白,为什么main在B不能乱扔未在声明例外main的签名A.
为什么Java设计者决定强制执行这样的约束,如果编译器没有强制执行约束,它会在什么情况下导致问题呢?
对于它的价值,这里是执行此规则的JLS的相关部分.
首先,§8.4.8.2.隐藏(通过类方法)给出了适用于此的方法隐藏的定义:
如果类C声明或继承了一个
static方法m,那么m就说隐藏任何方法m',其中签名m是m'C的超类和超接口中签名的子签名(第8.4.2节),否则代码可以访问在C.
然后,§8.4.8.3.覆盖和隐藏的要求指出:
覆盖或隐藏另一个方法的方法(包括实现
abstract接口中定义的方法的方法)可能不会被声明为抛出比重写或隐藏方法更多的已检查异常.更准确地说,假设B是类或接口,A是B的超类或超接口,B中的方法声明
m2覆盖或隐藏m1A中的方法声明.然后:
如果
m2有一个throws子句提到任何已检查的异常类型,那么m1必须有一个throws子句,否则会发生编译时错误.对于
throws子句中列出的每个已检查的异常类型m2,相同的异常类或其中一个超类型必须出现在该throws条款的擦除(第4.6节)中m1; 否则,发生编译时错误.
换句话说,错误消息不是编译器中的一些疏忽,也不是对规范的误解; JLS特别努力提到throws子句冲突是方法隐藏的错误(即,使用静态方法).在每个版本的JLS中都有与此类似的语言.
但是,在这种情况下,我无法明确回答您为何存在约束的问题.我无法想象任何需要约束的情况,因为调用哪个静态方法实现的问题总是在编译时完全解决,与实例方法不同.
我敢打赌少量资金,无论谁先把这种约束放在langspec中,都只是过于谨慎,认为防止某些东西比允许它更安全,然后发现它会导致问题.Java语言设计不是没有公平分享有缺陷的功能(检查异常是其中之一),这可能是另一个,但这只是猜测.
| 归档时间: |
|
| 查看次数: |
245 次 |
| 最近记录: |