44

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?

nickb
  • 59,313
  • 13
  • 108
  • 143
John Doe
  • 9,414
  • 13
  • 50
  • 69

3 Answers3

81

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.

Reinderien
  • 11,755
  • 5
  • 49
  • 77
Maurício Linhares
  • 39,901
  • 14
  • 121
  • 158
5

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 potential sources / causes of unchecked exceptions, and many of those sources / causes would actually be 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 a 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 damage (e.g. to important data structures) before triggering the exception. In general, you have no way of knowing whether the application can recover, or whether attempting to recover can do worse damage.

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.

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
  • That's a good point. But what do you mean saying "and attempt to recover from RuntimeException"? I didn't try to do that, actually one does not need to recover from RuntimeException. Or does one? – John Doe Jun 10 '12 at 08:41
  • By "attempt to recover" I mean do something other than allowing or causing the application to exit. It is not clear whether your code does that or not. (It depends what happens in the enclosing code.) Anyway I'm not saying that you *do* do this. Rather, I'm offering general advice which applies whenever your code catches one of the root exception classes. – Stephen C Jun 10 '12 at 09:01
-1

Any order the compiler will accept is correct.

The compiler will tell you which exceptions are being caught out of order.

user207421
  • 305,947
  • 44
  • 307
  • 483
  • @downvoter Explanation please. No error here. Both other answers agree. If you disagree please do so explicitly, but be prepared to cite chapter and verse. – user207421 Jan 24 '15 at 23:37
  • Your answer doesn't help OP and all the other readers with similar problems. – Evgenij Reznik Feb 14 '19 at 12:44
  • @user1170330 Of course it does. You just compile, read the error messages, and fix accordingly. – user207421 Feb 14 '19 at 23:09
  • Almost every error can be fixed with the help of the compiler. Then why bother looking for help on SO? – Evgenij Reznik Feb 15 '19 at 09:00
  • @user1170330 I agree entirely. Almost every error can indeed be fixed with the help of the compiler. Looking here on SO is a last resort when the compiler isn't helping. Computer programmers should be competent at understanding and rectifying 90% of compilation errors on their own; they should then refer to standard normative references; and only then should they seek outside help if necessary. Sadly there are far too many members here who reverse that order: as a consequence, there are far too many trivial questions here. – user207421 May 08 '19 at 06:52