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)
After the constructor I create the exception (inside the class 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). 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
. A RuntimeException
, such as: IllegalArgumentException
or NullPointerException
, does not have to be included in a method signature, so you will alleviate your compiler error.
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; 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.
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.
You can read more in the Java Language Specification:
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. 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).
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. 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).
While I'm at it, you probably shouldn't use NoSuchElementException
, as it's used in the JRE... use a different name.