Java unreachable catch block compiler error
A RuntimeException
could be thrown by any code. In other words, the compiler can't easily predict what kind of code can throw it. A RuntimeException
can be caught by a catch(Exception e)
block.
IOException
, however, is a checked exception - only method calls which are declared to throw it can do so. The compiler can be (reasonably) confident that it can't possible occur unless there are method calls which are declared to throw it.
The Java compiler simply doesn't consider the "there's no code at all within the try block" situation - it always allows you to catch unchecked exceptions, as in all reasonable scenarios there will be code which could potentially throw an unchecked exception.
From section 14.21 of the JLS:
A catch block C is reachable iff both of the following are true:
- Some expression or throw statement in the try block is reachable and can throw an exception whose type is assignable to the parameter of the catch clause C. (An expression is considered reachable iff the innermost statement containing it is reachable.)
- There is no earlier catch block A in the try statement such that the type of C's parameter is the same as or a subclass of the type of A's parameter.
Arguably the compiler should realize that there are no expressions within the try block in your first case... it looks like this is still an unreachable catch clause, to me.
EDIT: As noted in comments, section 14.20 contains this:
It is a compile-time error if a
catch
clause catches checked exception type E1 but there exists no checked exception type E2 such that all of the following hold:
- E2 <: E1
- The
try
block corresponding to thecatch
clause can throw E2- No preceding
catch
block of the immediately enclosing try statement catches E2 or a supertype of E2.
unless E1 is the class Exception.
So it looks like that's what you're actually running foul of, but the spec isn't as clear as it could be in terms of unreachable catch blocks in 14.21.
Custom Exception class shows Unreachable catch block everytime
Obviously, you are not doing anything that'd generate a MyException
. First write a method with the signature throws MyException
, call it and then your problem is solved. Here is an example:
public void someMethod()throws MyException
{
//some condition here.
//if met..
throw new MyException("cause");
}
and modify your main code as:
try {
someMethod();
System.out.println("this");
} catch (MyException e) {
// TODO: handle exception
}
Unreachable code compiling without error - How?
I believe these are the relevant quotes from JLS 14.21:
An empty block that is not a switch block can complete normally iff it is reachable.
A non-empty block that is not a switch block can complete normally iff the last statement in it can complete normally.
The first statement in a non-empty block that is not a switch block is reachable iff the block is reachable.
Every other statement S in a non-empty block that is not a switch block is reachable iff the statement preceding S can complete normally.
So your
System.out.println("I am unreachable??!!!");
statement is reachable iff (that means "if and only if") the try statement can complete normally, which leads to the next quote:
A try statement can complete normally iff both of the following are true:
The try block can complete normally or any catch block can complete normally.
If the try statement has a finally block, then the finally block can complete normally.
Since your catch
block can complete normally and you have a finally
block that can complete normally, the try
statement can complete normally. Hence the System.out.println("I am unreachable??!!!");
statement following it is deemed reachable, regardless of the return;
statement inside the try
block.
Note the or
in
The try block can complete normally or any catch block can complete normally.
This requires either the try
block or at least one of the catch
blocks to complete normally. It doesn't require both the try
block and catch
block to complete normally.
Finally, the logic behind this behavior:
The compiler is not supposed to analyze whether a try block can or cannot throw an Exception
. The reason is that the Exception
class hierarchy includes both checked and unchecked exceptions, and unchecked exceptions are not declared in throws
clauses (if you replaced Exception
with some checked exception, such as IOException
, the compiler would complain that your try block never throws that exception, which would make the catch
block unreachable).
Therefore, since you have a catch (Exception e)
block which can complete normally, the compiler assumes that this catch block it reachable, and therefore the entire try statement can complete normally, even though the try
block cannot complete normally.
The finally block, if present, must also be able to complete normally, since the finally
block is also executed, so if it couldn't complete normally, the entire try statement couldn't complete normally.
Unreachable catch block for ClassNotFoundException. This exception is never thrown from the try statement body
The error you posted:
Unreachable catch block for ClassNotFoundException
. This exception is never thrown from the try statement body
Your catch
block is the problem:
catch(ClassNotFoundException e){
e.printStackTrace();
}
ClassNotFoundException
is a checked exception and is never thrown by the code inside your try
block - see this page
Unreachable catch block for PSQLException. This exception is never thrown from the try statement body
PSQLException
is a checked exception. That means methods which throw that exception are required to document it in their signature. The compiler has detected that no code in your try block throws that type of exception. It knows that the catch block is redundant and is likely a user error, so it produces a failure so you can fix it.
Exception
is a broader classification and includes the set of all unchecked exceptions, which are not required to be documented in a method signature. In this case, the compiler doesn't know exactly what might be thrown, but it knows that something might be. So in this case, the catch block is not (necessarily) redundant, and so it will not report the same failure.
Unreachable code- try-catch-finally
This is the relevant part of JLS 14.21:
A
try
statement can complete normally iff both of the following are true:
The
try
block can complete normally or anycatch
block can complete normally.If the
try
statement has afinally
block, then thefinally
block can complete normally.
In this case, although your try block can't complete normally, it has a catch block that can complete normally. The finally block can also complete normally.
The try
statement is reachable and can complete normally, therefore the statement after it is reachable.
If you remove the catch
block, the first bullet in the above quoted section is no longer true - which means the try
statement can't complete normally, and the statement following it is unreachable.
Does java compiler optimize unreachable exception catch branches?
The javac compiler really doesn't do much of optimisation. But simple dead code detections and optimisations are yet possible.
In your example: the compiler can easily detect that the try block is empty. Empty try blocks can't throw, so all catch block code is essentially dead.
So the compiler could go in and simple drop the whole try/catch altogether here. Then there is nothing left that could throw an exception.
Which, when we use javap is exactly what we find in bytecode:
void methodThrowsException();
Code:
0: return
And yes, the other answer is fully correct: this only works this way because you are using Exception
, a more specific (checked) subclass will lead to a compiler error.
Java DateTime, Unreachable catch block for ParseException
The only checked exception that your try
block throws is not a ParseException
, which is what a SimpleDateFormat
would throw, but a DateTimeParseException
, which is what LocalDate.parse
throws, and a DateTimeParseException
is not a ParseException
.
The compiler sees the catch
block as unreachable because the ParseException
is never thrown from the try
block.
Just catch DateTimeParseException
instead.
} catch (DateTimeParseException e) {
Note that because it's a RuntimeException
, it's not absolutely necessary to catch it at all. But since you are already attempting to have "visibility", which is a good thing, and you're already attempting to catch an exception, just catch the correct exception type.
Related Topics
How to Check If a String Starts with One of Several Prefixes
Turning an Executorservice to Daemon in Java
How to Serialize an Object That Includes Bufferedimages
How to Create a Jagged 2D Array in Java
How to Use Jersey as Jax-Rs Implementation Without Web.Xml
How to Change Java Logging Console Output from Std Err to Std Out
Null Pointer Exception While Using Java Compiler API
Modifier Static Is Only Allowed in Constant Variable Declarations
Howto Extract Mimetype from a Byte[]
Why Should I Override Hashcode() When I Override Equals() Method
Getting Xml Node Text Value with Java Dom
Writing in the Beginning of a Text File Java
How to Write and Read Java Serialized Objects into a File
How to Add New Methods to the String Class in Java
Zoom Box for Area Around Mouse Location on Screen
Why Can't You Reduce the Visibility of a Method in a Java Subclass