我正在使用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
子句中提及已检查异常的限制是什么?
答案 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
,因为它不会引起后顾之忧。