2

我对例外有一些疑问。

谁能告诉我为什么 java 不允许我们在子类中创建 Checked Exception 而它允许在子类中创建 Unchecked 异常

下面的示例在我使用 'throws IOException' 时抛出编译时错误,但是当我在子类中使用 'throws ArithmeticException' 时它不会抛出任何错误。我只是想知道它背后的实际原因,请问可以吗?

这是代码(你会得到编译时错误)

package com.exception.test;

import java.io.IOException;

public class Parent {

    void msg()  {
        System.out.println("Parent...");
    }

    public static void main(String[] args) {
        Parent parent = new Child();
        parent.msg();
    }
}


class Child extends Parent {

    void msg() throws IOException   {
        System.out.println("Child...");
    }

}

//使用unCheckedException

package com.exception.test;

import java.io.IOException;

public class Parent {

    void msg()  {
        System.out.println("Parent...");
    }

    public static void main(String[] args) {
        Parent parent = new Child();
        parent.msg();
    }
}


class Child extends Parent {

    void msg() throws ArithmeticException   {
        System.out.println("Child...");
    }

}
4

4 回答 4

5

如果子类方法声明它可以抛出父类没有的已检查异常,则它违反了Liskov 替换原则,这是面向对象编程的基石之一。

考虑这段代码,Child.msg声明抛出一个检查异常:

void doMsg(Parent p) {
    p.msg();
}

如果您传入子对象,程序语义就会中断,因为现在既没有捕获也没有抛出已检查的异常:不再“检查”异常。

由于可以在任何地方抛出未经检查的异常,因此声明抛出一个除了文档之外没有其他用途。因此可以安全地允许它。

于 2013-06-04T09:09:03.990 回答
0

检查的异常可以在覆盖时缩小,但不能扩大。未检查的异常不需要被覆盖的方法捕获

从java规范

throws 子句中命名的检查异常类是方法或构造函数的实现者和用户之间契约的一部分。覆盖方法的 throws 子句可能不会指定此方法将导致抛出任何已检查的异常,而覆盖方法的 throws 子句不允许抛出该异常。

于 2013-06-04T09:48:04.260 回答
0

父类中的msg()方法可以抛出它喜欢的任何未经检查的异常。因此,如果您明确声明您的孩子抛出未经检查的异常,您实际上并没有更改合同。您的子方法可能会抛出ArithmeticException,但您的父方法也可能会抛出。

于 2013-06-04T09:09:14.637 回答
0

不幸的是,您遇到了 Java 的另一个缺陷,即检查异常。您收到的错误是所有 Java 专业人员都面临的一个实际问题:您正在使用一些代码实现一个方法,该方法恰好抛出一个未由超类方法声明的检查异常。声明的检查异常是 Java 方法签名的一部分;您可以减少子类中的列表,但不能扩展它。

如果这不仅仅是一个“为什么”的问题,并且您需要一种解决方法,那么标准的成语是

try {
   ...code that throws the checked exception...
} catch (TheCheckedException e) { throw new RuntimeException(e); }

这称为异常包装。如果你有不止一个或两个未声明的检查异常,你也可以使用相反的习惯用法,确保所有声明的异常透明地传播并且所有未声明的异常都被包装:

try { 
   ...code that throws various checked exceptions...
}
catch (DeclaredEx1 | DeclaredEx2 | RuntimeException e) { throw e;} 
catch (Exception e) { throw new RuntimeException(e); }
于 2013-06-04T09:17:54.877 回答