删除重写方法中的抛出,编译器在调用时需要一个 try/catch 块



>我有一个子类,我正在覆盖继承的父方法:我正在从方法声明中删除 throws 子句。

现在,使用多态性,my 实例的运行时类型应该确定方法实现;然而,当我尝试编译时,编译器抱怨并希望在方法调用周围有一个 try/catch 块,就好像正在调用超类方法而不是子类版本一样?

我知道我可以删除抛出声明或缩小覆盖时可能抛出的检查异常的范围。为什么这仍然引发异常?

class A{
    void foo()throws Exception{throw new Exception();}
}    
class SubB extends A{
    @Override
    void foo(){  System.out.println("B");  
}
public static void main(String[] args) {
    A a = new SubB();
    a.foo(); //compiler reports: unhandled exception type Exception 
}
编译器

会引发异常A但是,如果您告诉编译器这是一个实际的SubB对象,它将停止抱怨

SubB b = new SubB();
b.foo();

发生这种情况是因为将SubB实例分配给a会消除该实例是SubB的知识。 作为一个Aa.foo()现在可以(就JLS而言(抛出Exception

编译时类型知识基于变量的声明类型,而不是任何(假设的(推断类型(如果变量内容(。

编译器

是对的。 该行

A a = new SubB();

"表示"创建类SubB的实例并将其分配给类型为 A 的变量"。

这意味着从这一点开始,变量a的类型是A,而不是SubB。但是foo() A中定义,必须由调用方重新引发或捕获未经检查的异常。这是编译器告诉你的。

在行 a.foo()编译器已经"不知道"实际实例类型是SubB。它将其视为A .

最新更新