1

我正在用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);
        }   
    }
}

显示错误:

命令窗口

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

void show() throws IOException{

它工作正常......

我又做了一个实验:

void show() throws Exception{

但它也显示错误:

命令窗口

据我了解,这是因为重写方法的子句应该在超类方法的子句中throws提及确切的检查异常。throws

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

我刚刚尝试过......这个错误告诉我什么我不知道......

任何人都可以解释它所说的内容以及在throws覆盖方法的子句中提及检查异常的约束是什么?

4

2 回答 2

3

样本中有两个相关的错误:

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);
        }   
    }
}
于 2014-08-09T16:04:12.350 回答
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类型可以使用上面的代码(对 an 的捕获Exception也适用于它的任何子类型),因此,Java 将允许您IOException在派生中声明,因为它不会引起任何担忧稍后的。

于 2014-08-09T16:00:05.967 回答