java - 在重写方法中检查'throws'的异常

时间:2014-08-09 15:55:56

标签: java exception inheritance override throws

我正在使用java中的方法覆盖来练习异常处理机制...我的代码如下:

class base {
    void show() {    
        System.out.println("in base class method");    
    }
}

class derived extends base {
    void show() throws IOException {    
        System.out.println("in derived class method");
        throw new IOException();
    }
}

class my {
    public static void main(String[] args) {  
        try {
            base b = new derived();
            b.show();
        }    
        catch (IOException e) {
            System.out.println("exception occurred at :" + e);
        }   
    }
}

显示错误:

cmd window

所以,我更正了以下内容:

void show() throws IOException{

它正常工作......

我做了另一个实验:

void show() throws Exception{

但它也显示错误:

cmd window

据我所知,这是因为重写方法的throws子句应该在超类方法的throws子句中提到精确检查的异常。

与第二种情况一样,如果我在throws子句中编写IOException的超类Exception,它也会显示错误。为什么?即使Exception是所有例外的父类。

我刚试验过......这个错误告诉我不知道......

任何人都可以解释它说的内容以及在重写方法的throws子句中提及已检查异常的限制是什么?

2 个答案:

答案 0 :(得分:2)

样本中有两个相关错误:

1) 您的基类方法为派生类方法提供"模板" 基本条件

因此,基类应该声明一个超集,即派生类的相同异常类或基类异常类。你不能声明它什么都不抛出,因为那时标准就不匹配了。

因此,如果您的派生类方法是这样的:

class Derived extends Base {
    void show() throws IOException {
        //...
    }
}

然后基类方法"必须"是:

class Base {
    void show() throws /*Same or base classes of IOException*/ {
        //...
    }
}

所以这两个都有效:

class Base {
    void show() throws Exception {
        //...
    }
}

class Base {
    void show() throws Throwable {
        //...
    }
}

2)当您尝试上述操作时,show方法的整体声明现在变为throws Exception。因此,使用此show的任何人都必须捕获该异常。

main方法中,您正在捕捉IOException。这将不再有效,编译器抱怨"确定你正在捕获IOException,那么Exception的所有其他可能性呢?"这是您展示的第二个错误。

要解决此问题,请更改main方法catch以包含基类中声明的Exception

class My {
    public static void main(String[] args) {
        try {
            base b = new derived();
            b.show();
        }
        /* NOTE: CHANGED FROM IOException TO Exception */
        catch (Exception e) {
            System.out.println("exception occurred at :" + e);
        }   
    }
}

答案 1 :(得分:1)

重写方法在throws子句中可能只包含与超级方法相同的已检查异常,或者最多只包含派生类型。

例如,如果你说

class Base {

    public void foo(int y) throws IOException {
        // ...
    }
}

class Derived extends Base {

    public void foo(int y) throws Exception {
        // ...
    }
}

然后你的编译器会说foo内的Derived方法与其超类中的throws子句不兼容。

另一种方式可行,因为如果我说

class Base {

    public void foo(int y) throws Exception {
        // ...
    }
}

class Derived extends Base {

    public void foo(int y) throws IOException {
        // ...
    }
}
好的,没关系。

为什么。

考虑一下你的方法的用法。 Java希望您以多态方式使用该方法,例如

Base a = new Derived();
a.foo(3);

因此,编译器将强制您捕获foo在声明的变量类型(Base)中抛出的异常。所以你的代码将成为

Base a = new Derived();
try {
    a.foo(3);
} catch (Exception e) {
    // ...
}

因此,您在Exception类型中声明的Derived子类型对于上面的代码是正常的(Exception的捕获对任何代码都适用它的子类型也是如此)因此,Java允许你在派生中声明IOException,因为它不会引起后顾之忧。