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现在抛出exception。 这不会编译,因为重写方法不能抛出新的exception。

什么是最好的解决方案?

  • 将所需的例外传播给Father 。 对我来说,这是对封装,inheritance和一般OOP( Father可能抛出永远不会发生的exception)。
  • 使用RuntimeException代替? 此解决方案不会将Exception传播给Father ,但Oracle文档和其他来源声明在“客户端代码无法执行任何操作”时应使用exception类。 这不是那种情况,这个exception对于恢复blablabla很有用(为什么使用RuntimeException导致错误?)。
  • 其他..

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

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

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

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

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

其他选项是允许Super类声明ParentException然后子重写方法可以声明任何ParentException子类ParentException

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

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

我认为一般的经验法则是

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

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

将所需的exception传播给父..对我来说,这是针对封装,inheritance和一般OOP(父亲可能抛出和永远不会发生的exception)

Au逆转:这是好的 OO。 图像来电者方:

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

工厂可以返回FatherChild的例子或像Brother一样完全不同的东西。 但方法1的合同在所有情况下必须相同。 此合同包括已检查的例外情况。 这是Liskov替代原则,是OO的基本规则之一。

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