简体   繁体   English

处理Java中重写方法层次结构中的异常

[英]Handling exceptions in a hierarchy of overridden methods in Java

Consider a Java class hierarchy such as: 考虑Java类层次结构,例如:

abstract class Exp { public void generate(); }
class EffExp extends Exp {...}
clas PureExp extends Exp {...}
class NewExp extends EffExp {...}
etc, etc.

The implementation of generate inside NewExp was changed to throw an IOException . NewExp中的generate实现被更改为抛出IOException

public void generate() throws IOException {...}

The other implementations of generate don't do any IO hence don't need to throw it. generate的其他实现不执行任何IO,因此不需要抛出它。 The compiler complains and forces me to declare all methods in the class hierarchy to throw the exception. 编译器抱怨并强制我声明类层次结构中的所有方法以抛出异常。 Is this really the only way forward? 这真的是前进的唯一途径吗? It seems rather intrusive. 这似乎是相当干扰的。

I could of course catch the exception where it happens, inside NewExp , but that doesn't really make sense. 我当然可以在NewExp捕获它发生的异常,但这并没有多大意义。 The exception should propagate to the top and stop the program execution. 异常应传播到顶部并停止程序执行。

The more general question here is: if you have a hierarchy of methods that override each other, do they all have to be declared to throw the same set of exceptions? 这里更一般的问题是:如果你有一个覆盖彼此的方法层次结构,那么它们是否都必须被声明为抛出相同的异常集?

Just remember One Rule : - 记住一条规则 : -

  • You cannot add more restriction to the method you override. 您无法为覆盖的方法添加更多限制。 The restrictions can be for eg : - adding an new Checked Exception , decreasing the method visibility. 限制可以是例如: - 添加新的Checked Exception ,降低方法可见性。

So, if you have to (no choice), make your overriding method throw a Checked Exception (Note that, you can add a unchecked Exception, though, but it wouldn't make any sense), just add the exception in the throws clause of the method you are overriding. 所以,如果你必须(没有选择),让你的重写方法抛出一个Checked Exception (注意,你可以添加一个未经检查的Exception,但它没有任何意义),只需在throws子句中添加异常你重写的方法。

So, in simple words, the signature of your overridden method should match exactly with the one that overrides it. 因此,简单来说, overridden方法的签名应该与覆盖它的方法完全匹配。


Now the simple reasoning behind this is - Polymorphism . 现在这背后的简单推理是 - Polymorphism

In polymorphism, as you know that, you can have a super type reference point to a sub class object. 在多态性中,如您所知,您可以拥有一个子类对象的super type引用点。 So, you can have: - 所以,你可以: -

SupClass ref = new SubClass();
ref.method1();

Now, while checking for the existence of method1 , compiler is only concerned about the reference type. 现在,在检查method1是否存在时,编译器只关心引用类型。 So, it checks in SupClass , and allows the access accordingly. 因此,它检查SupClass ,并允许相应的访问。

Now, imagine what happens, when at runtime, when ref is actually pointing to SubClass object, JVM finds that method1 throws a new exception, that was not checked by the compiler . 现在,假设发生了什么,当在运行时,当ref实际指向SubClass对象时,JVM发现method1抛出一个新的异常, compiler没有检查过。 It will crash. 它会崩溃。 That is why it is not allowed. 这就是为什么不允许这样做的原因。

Suppose the scenario is something like : 假设场景类似于:

abstract class Exp { public void generate(); }
class EffExp extends Exp { public void generate throw IOException(....)....}
clas PureExp extends Exp {public void generate(....)....}

We use abstract class notation so that we could implement our other classes without worrying about the actual implementation . 我们使用抽象类表示法,以便我们可以实现我们的其他类而不必担心实际的实现。 If we make actual; 如果我们实际; implementation narrowed ie throw Exception in some case and don't throw in some other case then its clearly a violation of Java being Robust. 实现范围缩小,即在某些情况下抛出异常并且不抛弃其他情况,那么它显然违反Java是强健的。 So you need to be clearly in sync. 所以你需要明确同步。 for all the methods. 对于所有方法。

Although you can increase the visibility by throwing a Parent "Exception". 虽然您可以通过抛出父“异常”来提高可见性。

In abstract class you can define to throw java.lang.Exception 在抽象类中,您可以定义抛出java.lang.Exception

abstract class Exp { public abstract void generate() throws Exception; }

And in derived classes be more specific about what type of exception you throw. 在派生类中,更具体地说明您抛出的异常类型。

Just consider this simple hypothetical code that, let's assume... fits your description: 只要考虑这个简单的假设代码,让我们假设...符合您的描述:

Exp ex = new NewExp(); 
try {
ex.generate(); //It should throw an exception, but has no such method signature. 
} catch(AnException e) { //Nope, not allowed.
 ...
}

Does it need to throw a checked exception. 是否需要抛出已检查的异常。 Could you wrap it in a runtime exception? 你能把它包装在运行时异常中吗?

public void generate() {
     try {
     ....
     } catch (IOException e ){
        RuntimeException re = new RuntimeException();
        re.initCause(e);
        throw re;
     }   
}

(not checked this for compilation but it should give you a general idea (没有检查这个编译,但它应该给你一个大致的想法

If you are overriding a method, the overridden method in a superclass can only declare to throw that exception (checked) or its superclass. 如果要覆盖方法,则超类中的重写方法只能声明抛出该异常(已检查)或其超类。 Otherwise you'll loose polymorphism and hence not allowed in Java 否则你将失去多态性,因此在Java中不允许

  1. We can not introduce a new checked exception in the overridden method but can have child checked exception or the same exception as handled in the parent class. 我们不能在重写方法中引入新的已检查异常,但可以具有子检查异常或与父类中处理的异常相同的异常。 Even if we do then if we refer to a child object with the parent reference it then compiler will force to catch the exception declared in the parent class method then look at the below example: 即使我们这样做,如果我们使用父引用引用子对象,那么编译器将强制捕获在父类方法中声明的异常,然后查看下面的示例:

     class Parent{ public void method throws IOException{ } } class Child extends Parent{ public void method throws SQLException{ } } class Test{ public static void main(){ Parent p=new Child(); try{ p.method(); }catch(IOException e){ e.printStackTrace(); } } } 

    In the above program, child class method throws SQLException but Compiler will force to catch IOException. 在上面的程序中,子类方法抛出SQLException,但Compiler将强制捕获IOException。 Because at compile time it is not known to the compiler as child object is being referred from a parent reference. 因为在编译时编译器不知道子对象是从父引用引用的。 But we can declare any unchecked exception as compiler will not enforce try/ctach or throws for them. 但是我们可以声明任何未经检查的异常,因为编译器不会为它们强制执行try / ctach或throws。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM