Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Order of catching exceptions in Java

Tags:

java

exception

If I'm not mistaken, subclasses of Exceptions should be caught first. But having to catch any RuntimeException and a concrete checked Exception, which should be caught at first?

try {     ... } catch(RuntimeException e) {     ... } catch(IOException e) {     ... } 

Is this order a correct one? Or is it correct but a bad option?

like image 971
John Doe Avatar asked Jun 09 '12 21:06

John Doe


People also ask

Which order should we catch the exceptions?

Order of exceptions If you have multiple catch blocks for a single try and if the exceptions classes of them belong to the same hierarchy, You need to make sure that the catch block that catches the exception class of higher-level is at last at the last in the order of catch blocks.

Why does order matter when catching exceptions?

It is important to remember that exception subclass must come before any their superclasses. This is because a catch statement that uses a superclasses will catch exception of that type plus any of its subclasses. Thus, a subclass would never be reached if it came after its superclass.

Does order of catch statements matter?

The order of catch blocks does matter It's because if we handle the most general exceptions first, the more specific exceptions will be omitted, which is not good, as Java encourages handling exceptions as much specific as possible.

What is the order of multiple catch blocks?

All catch blocks must be ordered from most specific to most general, i.e. catch for ArithmeticException must come before catch for Exception.


2 Answers

The order is whatever matches first, gets executed (as the JLS clearly explains).

If the first catch matches the exception, it executes, if it doesn't, the next one is tried and on and on until one is matched or none are.

So, when catching exceptions you want to always catch the most specific first and then the most generic (as RuntimeException or Exception). For instance, imagine you would like to catch the StringIndexOutOfBoundsException thrown by the String.charAt(index) method but your code could also throw a NullPointerException, here's how you could go to catch the exceptions:

String s = null; try {   s.charAt(10); } catch ( NullPointerExeption e ) {   System.out.println("null");   e.printStackTrace(); } catch ( StringIndexOutOfBoundsException e ) {   System.out.println("String index error!");   e.printStackTrace(); } catch ( RuntimeException e ) {   System.out.println("runtime exception!");   e.printStackTrace(); } 

So, with this order, I am making sure the exceptions are caught correctly and they are not tripping over one another, if it's a NullPointerException it enters the first catch, if a StringIndexOutOfBoundsException it enters the second and finally if it is something else that is a RuntimeException (or inherits from it, like a IllegalArgumentException) it enters the third catch.

Your case is correct as IOException inherits from Exception and RuntimeException also inherits from Exception, so they will not trip over one another.

It's also a compilation error to catch a generic exception first and then one of it's descendants later, as in:

try {   // some code here } catch ( Exception e) {   e.printStackTrace(); } catch ( RuntimeException e ) { // this line will cause a compilation error because it would never be executed since the first catch would pick the exception   e.printStackTrace(); } 

So, you should have the children first and then the parent exceptions.

like image 132
Maurício Linhares Avatar answered Oct 16 '22 20:10

Maurício Linhares


Is this order a correct one? Or is it correct but a bad option?

Neither. As other answers have said, the compiler should tell you if you put simple catches in an order where one masks another.

But there is another potential issue in your code: should you actually be catching RuntimeException at all. The issue is that there are many sources / causes of uunchecked exceptions, and many of those sources / causes are actually bugs in your application.

Using the catch to log a diagnostic as part of an emergency shutdown is fine, but if you catch and attempt to recover from RuntimeException, you need to be careful that you are not sweeping a serious problem under the carpet:

  • Make sure that you log the exception and its stacktrace, no matter what.

  • Consider whether is is wise to attempt to recover. If you've got an unknown bug, it could have done unpredictable damage before triggering the exception. You've no way of knowing whether the application can recover, or whether it might do worse damage by attempting to continue.

The same advice applies to catching Exception and Throwable / Error. And it is more critical with Throwable / Error because of the nature of the damage that could well have already occurred.

like image 44
Stephen C Avatar answered Oct 16 '22 21:10

Stephen C