Java中的异常和继承

时间:2012-10-19 16:47:57

标签: java exception inheritance

假设我们有这个问题

public class Father{
    public void method1(){...}
}

public class Child1 extends Father{
    public void method1() throws Exception{
    super.method1();
    ... 
    }

}

Child1扩展Father并覆盖method1,但鉴于实施Child1.method1现在会抛出异常。这不会编译,因为重写方法不能抛出新的异常。

什么是最佳解决方案?

  • 将所需的例外传播到Father。对我而言,这是针对封装,继承和一般OOP(Father可能引发永远不会发生的异常。)
  • 使用RuntimeException代替?此解决方案不会将Exception传播到Father,但Oracle文档和其他来源声明,当“客户端代码无法执行任何操作”时,应使用该类异常。不是这种情况,这个例外对于恢复blablabla很有用(为什么使用RuntimeException代替它?)。
  • 其他..

5 个答案:

答案 0 :(得分:4)

使用RTE并不是一个坏主意。这是Spring框架的方法,它工作得很好。如果您正在实施应用程序,请使用此解决方案。

如果您正在实现公开API恕我直言的库,您应该使用已检查的异常。在这种情况下,您应该创建自己的例外BaseExceptionmethod()的方法Father将抛出它。定义ChildException extends BaseException并声明子类的method1()以抛出它。

这不破坏封装:基类抛出基本异常。它对具体的例外情况一无所知。 Child类抛出具体的异常但是扩展了基本异常,因此可以被客户端代码视为基本异常。

作为一个例子,我可以给你IOExceptionFileNotFoundException扩展它。您可以使用输入流捕获IOException,而具体流为FileInputStream并抛出FileNotFoundException。但客户不知道这一点。它捕获IOException

答案 1 :(得分:2)

如果超类方法没有声明Exception,则子类重写方法不能声明已检查的异常。因此,您只能使用未经检查的例外。

其他选项是允许Super类声明ParentException然后子被覆盖的方法可以声明任何属于ParentException

的子类的异常

答案 2 :(得分:1)

取决于什么会引发Child1中的异常。如果它有一些先决条件等,你可以随时使用RuntimeException的任何子类,例如IllegalArgumentException。

但是,如果存在某种CheckedException,那么逻辑建议您应该处理该方法本身并以其他方式冒泡消息。

我认为一般的经验法则是

如果您知道如何处理它..使用已检查的异常,否则未经检查的异常

答案 3 :(得分:0)

“throws”部分是方法签名的一部分。
这就是为什么“child”类的方法不是父类方法的重写。

答案 4 :(得分:0)

  

向父传播所需的异常..对我来说,这是针对封装,继承和一般OOP(父亲可能抛出和永远不会发生的异常)

Au contraire:这是 OO。图像来电者方:

Father f = factory.getSomeImplementation();
f.method1();
// user has no chance to see the `Exception` of Child coming...

工厂可以返回FatherChild的实例或与Brother完全不同的内容。但所有案例中method1的合同必须相同。此合同包括已检查的例外情况。这是Liskov替代原则,是OO的基本规则之一。

因此,如果异常是method1的业务合同的一部分,则必须在根目录中声明。如果不是(例如一个简单的参数检查),那么RuntimeException是无论如何都要去的路线(即使没有继承)。