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:
- catching and handling it with a
try ... catch
statement, or - declaring that the enclosing method or constructor
throws
it1.
- catching and handling it with a
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.Throwable
class. Exceptions are divided into two categories:
- Checked exceptions are
Throwable
, andException
and its subclasses, apart fromRuntimeException
and its subclasses. - Unchecked exceptions are all other exceptions; i.e.
Error
and its subclasses, andRuntimeException
and 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 ... catch
statement. For example:public void doThings() { try { // do some things if (someFlag) { throw new IOException("cannot read something"); } // do more things } catch (IOException ex) { // deal with it <<<=== HERE } }
In the above, we put the statement that throws the (checked)
IOException
in the body of thetry
. Then we wrote acatch
clause to catch the exception. (We could catch a superclass ofIOException
… but in this case that would beException
and catchingException
is a bad idea.) -
You can declare that the enclosing method or constructor
throws
the exceptionpublic void doThings() throws IOException { // do some things if (someFlag) { throw new IOException("cannot read something"); } // do more things }
In 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 code has thrown a checked exception, or called some method or constructor that throws the checked exception, and
- it has not dealt with the exception by catching it or by declaring it as required by the Java language.
Your solution process should be:
- Understand what the exception means, and why it could be thrown.
- Based on 1, decide on the correct way to deal with it.
- Based on 2, make the relevant changes to your code.
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
try { ... } catch (NullPointerException ex) { }
If you squash exceptions, you are liable to make the runtime errors that triggered them much harder to diagnose. You are destroying the evidence.
The edge cases
There some situations where dealing with checked exceptions is a problem. One particular case is checked exceptions in static
initializers. For example:
private static final FileInputStream input = new FileInputStream("foo.txt");
The FileInputStream
is declared as throws 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 a try
… 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 static
block; for example:
private static final FileInputStream input;
static {
FileInputStream temp = null;
try {
temp = new FileInputStream("foo.txt");
} catch (FileNotFoundException ex) {
// log the error rather than squashing it
}
input = temp; // Note that we need a single point of assignment to 'input'
}
(There are better ways to handle the above scenario in practical code, but that’s not the point of this example.)
More Information
The Oracle Java Tutorial:
- The catch or specify requirement
… also covers checked vs unchecked exceptions. - Catching and handling exceptions
- Specifying the exceptions thrown by a method