假设我们有这个问题
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
代替它?)。答案 0 :(得分:4)
使用RTE并不是一个坏主意。这是Spring框架的方法,它工作得很好。如果您正在实施应用程序,请使用此解决方案。
如果您正在实现公开API恕我直言的库,您应该使用已检查的异常。在这种情况下,您应该创建自己的例外BaseException
。 method()
的方法Father
将抛出它。定义ChildException extends BaseException
并声明子类的method1()
以抛出它。
这不破坏封装:基类抛出基本异常。它对具体的例外情况一无所知。 Child类抛出具体的异常但是扩展了基本异常,因此可以被客户端代码视为基本异常。
作为一个例子,我可以给你IOException
和FileNotFoundException
扩展它。您可以使用输入流捕获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...
工厂可以返回Father
或Child
的实例或与Brother
完全不同的内容。但所有案例中method1
的合同必须相同。此合同包括已检查的例外情况。这是Liskov替代原则,是OO的基本规则之一。
因此,如果异常是method1
的业务合同的一部分,则必须在根目录中声明。如果不是(例如一个简单的参数检查),那么RuntimeException
是无论如何都要去的路线(即使没有继承)。