简体   繁体   English

重写的方法不会引发异常

[英]overridden method does not throw exception

I have a problem when compiling my code, I'm trying to make a method of a class throw an personalized exception, given some conditions. 我在编译代码时遇到问题,在某些条件下,我试图使类的方法引发个性化异常。 But at the time of compiling I get the message: 但是在编译时,我得到消息:

Overridden method does not throw exception 重写的方法不会引发异常

Here's the class and exception declaration: 这是类和异常声明:

public class UNGraph implements Graph

Graph is an interface with all the methods of UNGraph in it (the method getId() doesn't have the throws declaration on that script) Graph是一个接口,其中包含UNGraph所有方法(方法getId()在该脚本上没有throws声明)

After the constructor I create the exception (inside the class UNGraph): 在构造函数之后,我创建了异常(在类UNGraph中):

public class NoSuchElementException extends Exception {
    public NoSuchElementException(String message){
        super(message);
    }
}

Here is the method with the exception 这是例外的方法

public int getId(....) throws NoSuchElementException {
    if (condition is met) {
        //Do method
        return variable;
    }
    else{
       throw new NoSuchElementException (message);
    }
}

Obviously I don't want the method to throw an exception every time, just when the condition is not met; 显然,我不希望该方法每次都在不满足条件的情况下抛出异常。 and when it's met, I want to return a variable. 当它遇到时,我想返回一个变量。

The compiler is issuing an error because Java does not allow you to override a method and add a checked Exception (any user-defined custom exception that extends the Exception class). 编译器发出错误是因为Java不允许您重写方法并添加已检查的Exception(扩展Exception类的任何用户定义的自定义异常)。 Because it is clear that you want to handle the scenario where some condition is not met as an unexpected occurrence (a bug), your best option is to throw a RuntimeException . 因为很明显,您要处理满足某些条件的情况(意外发生)(错误),所以最好的选择是抛出RuntimeException A RuntimeException , such as: IllegalArgumentException or NullPointerException , does not have to be included in a method signature, so you will alleviate your compiler error. RuntimeException (例如: IllegalArgumentExceptionNullPointerException )不必包含在方法签名中,因此可以减轻编译器错误。

I suggest the following changes to your code: 我建议对您的代码进行以下更改:

//First: Change the base class exception to RuntimeException:
public class NoSuchElementException extends RuntimeException {
    public NoSuchElementException(String message){
        super(message);
    }
}

//Second: Remove the exception clause of the getId signature
//(and remove the unnecessary else structure):
public int getId(....) {
    if ( condition is met) { return variable; }
    //Exception will only be thrown if condition is not met:
    throw new NoSuchElementException (message);
}

The problem becomes clear when you have such code as this using your class and interface: 当使用类和接口编写如下代码时,问题就变得很明显:

Graph g = new UNGraph();
int id = g.getId(...);

The interface Graph doesn't declare that it throws the checked exception NoSuchElementException , so the compiler would allow this code without a try block or a throws clause on whatever method this code is in. But the overriding method clearly can throw the checked exception; Graph接口没有声明它抛出了被检查的异常NoSuchElementException ,因此编译器将允许此代码在没有任何代码的情况下使用try块或throws子句。但是,重写方法显然可以抛出被检查的异常; it has declared as much. 它已经宣布了很多。 This is the reason that an overriding method cannot throw more checked exceptions than an overridden or abstract method. 这就是为什么覆盖方法不能抛出比覆盖方法或抽象方法更多的检查异常的原因。 There would be a difference in how the calling code needs to handle checked exceptions, depending on the actual type of the object. 根据对象的实际类型,调用代码需要如何处理检查的异常会有差异。

Have the interface's method declaration declare that it throws NoSuchElementException or have the implementing class's method handle the NoSuchElementException itself. 让接口的方法声明声明它抛出NoSuchElementException或者让实现类的方法自己处理NoSuchElementException

You have to declare the throws NoSuchElementException in all superclasses for a checked exception, if you want the subclasses to throw a checked exception in that method. 如果要让子类在该方法中引发检查的异常,则必须在所有超类中为throws NoSuchElementException检查的异常声明throws NoSuchElementException

You can read more in the Java Language Specification : 您可以在Java Language Specification中阅读更多内容:

11.2. 11.2。 Compile-Time Checking of Exceptions 编译时检查异常

The Java programming language requires that a program contains handlers for checked exceptions which can result from execution of a method or constructor. Java编程语言要求程序包含用于检查异常的处理程序,这些异常可能是由于执行方法或构造函数而导致的。 For each checked exception which is a possible result, the throws clause for the method ( §8.4.6 ) or constructor ( §8.8.5 ) must mention the class of that exception or one of the superclasses of the class of that exception ( §11.2.3 ). 对于每个可能的结果检查异常,方法(第8.4.6节 )或构造函数(第8.8.5节 )的throws子句必须提及该异常的类或该异常的类的超类之一( 第§ 11.2.3 )。

This compile-time checking for the presence of exception handlers is designed to reduce the number of exceptions which are not properly handled. 这种检查异常处理程序是否存在的编译时检查旨在减少未正确处理的异常的数量。 The checked exception classes ( §11.1.1 ) named in the throws clause are part of the contract between the implementor and user of the method or constructor. throws子句中命名的已检查异常类(第11.1.1节 )是方法或构造函数的实现者与用户之间的契约的一部分。 The throws clause of an overriding method may not specify that this method will result in throwing any checked exception which the overridden method is not permitted, by its throws clause, to throw ( §8.4.8.3 ). 重写方法的throws子句可能不指定此方法将导致抛出任何检查的异常,而该异常将由其throws子句不允许抛出该覆盖的方法(第8.4.8.3节 )。


While I'm at it, you probably shouldn't use NoSuchElementException , as it's used in the JRE ... use a different name. 当我在使用它时,您可能不应该使用NoSuchElementException ,因为它在JRE中使用了……请使用其他名称。

这里 “异常与方法覆盖在Java中处理”就是答案。

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

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