New Java programmers frequently encounter errors phrased like this:
"error: unreported exception <XXX>; must be caught or declared to be thrown"
where XXX is the name of some exception class.
Please explain:
- What the compilation error message is saying,
- the Java concepts behind this error, and
- how to fix it.
First things first. This a compilation error not a exception. You should see it at compile time.
If you see it in a runtime exception message, that's probably because you are running some code with compilation errors in it. Go back and fix the compilation errors. Then find and set the setting in your IDE that prevents it generating ".class" files for source code with compilation errors. (Save yourself future pain.)
The short answer to the question is:
The error message is saying that the statement with this error is throwing (or propagating) a checked exception, and the exception (the
XXX) is not being dealt with properly.The solution is to deal with the exception by either:
try ... catchstatement, orthrowsit1.1 - There are some edge-cases where you can't do that. Read the rest of the answer!
Checked versus unchecked exceptions
In Java, exceptions are represented by classes that descend from the
java.lang.Throwableclass. Exceptions are divided into two categories:Throwable, andExceptionand its subclasses, apart fromRuntimeExceptionand its subclasses.Errorand its subclasses, andRuntimeExceptionand its subclasses.(In the above, "subclasses" includes by direct and indirect subclasses.)
The distinction between checked and unchecked exceptions is that checked exceptions must be "dealt with" within the enclosing method or constructor that they occur, but unchecked exceptions need not be dealt with.
(Q: How do you know if an exception is checked or not? A: Find the javadoc for the exception's class, and look at its parent classes.)
How do you deal with a (checked) exception
From the Java language perspective, there are two ways to deal with an exception that will "satisfy" the compiler:
You can catch the exception in a
try ... catchstatement. For example:In the above, we put the statement that throws the (checked)
IOExceptionin the body of thetry. Then we wrote acatchclause to catch the exception. (We could catch a superclass ofIOException... but in this case that would beExceptionand catchingExceptionis a bad idea.)You can declare that the enclosing method or constructor
throwsthe exceptionIn the above we have declared that
doThings()throwsIOException. That means that any code that calls thedoThings()method has to deal with the exception. In short, we are passing the problem of dealing with the exception to the caller.Which of these things is the correct thing to do?
It depends on the context. However, a general principle is that you should deal with exceptions at a level in the code where you are able to deal with them appropriately. And that in turn depends on what the exception handling code is going to do (at
HERE). Can it recover? Can it abandon the current request? Should it halt the application?Solving the problem
To recap. The compilation error means that:
Your solution process should be:
Example: throwing and catching in the same method
Consider the following example from this Q&A
If you have been following what we have said so far, you will realise that the
t()will give the "unreported exception" compilation error. In this case, the mistake is thatthas been declared asthrows IllegalAccessException. In fact the exception does not propagate, because it has been caught within the method that threw it.The fix in this example will be to remove the
throws IllegalAccessException.The mini-lesson here is that
throws IllegalAccessExceptionis the method saying that the caller should expect the exception to propagate. It doesn't actually mean that it will propagate. And the flip-side is that if you don't expect the exception to propagate (e.g. because it wasn't thrown, or because it was caught and not rethrown) then the method's signature shouldn't say it is thrown!Bad practice with exceptions
There are a couple of things that you should avoid doing:
Don't catch
Exception(orThrowable) as a short cut for catching a list of exceptions. If you do that, you are liable catch things that you don't expect (like an uncheckedNullPointerException) and then attempt to recover when you shouldn't.Don't declare a method as
throws Exception. That forces the called to deal with (potentially) any checked exception ... which is a nightmare.Don't squash exceptions. For example
If you squash exceptions, you are liable to make the runtime errors that triggered them much harder to diagnose. You are destroying the evidence.
Note: just believing that the exception never happens (per the comment) doesn't necessarily make it a fact.
Edge case: static initializers
There some situations where dealing with checked exceptions is a problem. One particular case is checked exceptions in
staticinitializers. For example:The
FileInputStreamis declared asthrows FileNotFoundException... which is a checked exception. But since the above is a field declaration, the syntax of the Java language, won't let us put the declaration inside atry...catch. And there is no appropriate (enclosing) method or constructor ... because this code is run when the class is initialized.One solution is to use a
staticblock; for example:(There are better ways to handle the above scenario in practical code, but that's not the point of this example.)
Edge case: static blocks
As noted above, you can catch exceptions in static blocks. But what we didn't mention is that you must catch checked exceptions within the block. There is no enclosing context for a static block where checked exceptions could be caught.
Edge case: lambdas
A lambda expression (typically) should not throw an unchecked exception. This is not a restriction on lambdas per se. Rather it is a consequence of the function interface that is used for the argument where you are supplying the argument. Unless the function declares a checked exception, the lambda cannot throw one. For example:
Even though we appear to have caught
IOException, the compiler will complain that:catchis catching an exception that is never thrown!In fact, the exception needs to be caught in the lambda itself:
(The astute reader will notice that the two versions behave differently in the case that a
deletethrows an exception ...)Edge case: two exceptions called Xyzzy
I have seen cases where a method has a
throws Xyzzyclause, and the compiler still complains thatXyzzymust be "caught or declared to be thrown". For example: Unreported exception ...... must be caught or declared to be thrown; despite *thrown* keyword.If you find yourself in this situation, look carefully at the fully qualified names of the exceptions. If the fully qualified names are different, then the exceptions are different. (Believe what the compiler is saying and try to understand it.)
More Information
The Oracle Java Tutorial: