15

Why is catching a RuntimeException using catch(Throwable exc) {} not considered a good programming practice? What is the right way to handle RuntimeExceptions?

Also, why does catch(Exception exc) {} not catch RuntimeException? How is this behavior implemented?

Makoto
  • 104,088
  • 27
  • 192
  • 230
SPS
  • 183
  • 1
  • 2
  • 10
  • 4
    That `catch` does catch `RuntimeException`. – Sotirios Delimanolis Jun 21 '14 at 18:20
  • 2
    Because unchecked exceptions usually are exception that you can avoid by performing a simple check with an `if` statement. I.E. `NullPointerException` can be avoided with `if(myObject != null)`. Also, `if` is faster than `try-catch`. Use `try-catch` when you really need it. – BackSlash Jun 21 '14 at 18:22
  • 4
    I would disagree that catching a RuntimeException is bad practice. Catching and then _ignoring_ the error... that's bad. – Tony Ennis Jun 21 '14 at 18:25

3 Answers3

27

Usually, a RuntimeException indicates a programming error (in which case you can't "handle" it, because if you knew to expect it you'd have avoided the error).

Catching any of these general exceptions (including Throwable) is a bad idea because it means you're claiming that you understand every situation which can go wrong, and you can continue on despite that. It's sometimes appropriate to catch Exception (but not usually Throwable) at the top level of the stack, e.g. in a web server - because usually whatever's gone wrong with a single request, you normally want to keep the server up and responding to further requests. I don't normally catch Throwable, as that includes Error subclasses which are normally used to indicate truly catastrophic errors which would usually be best "handled" by terminating the process.

Fundamentally, when there's an error you need to be very cautious about continuing with a particular task - you need to really have a pretty good idea about what the error means, as otherwise you could go ahead with a mistaken assumption about the state of the world, and make things worse. In most cases (not all), simply giving up on a request is better than trying to carry on regardless of a mysterious failure. (It does very much depend on context though - you might not care what went wrong when trying to fetch one piece of secondary information, for example.)

As for catching Exception not catching RuntimeException - that's simply not true. The only odd thing about RuntimeException is that it (and subclasses) are unchecked exceptions, whereas Exception and all other subclasses of Exception are checked.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • 1
    ....hi can you please elaborate how checked and unchecked exceptions behave differently ? – SPS Jun 24 '14 at 16:49
  • @SumitPalSingh: There's a lot of good information available already. Read the Java tutorial: http://docs.oracle.com/javase/tutorial/essential/exceptions/index.html – Jon Skeet Jun 24 '14 at 16:52
  • By leaving `Error` instances bubble up, how do we know which component will catch them ? How will this or those component(s) log those errors ? How do we know what happened once the program crashed due to an error ? Some errors can be difficult to reproduce. – Stephan Jan 22 '22 at 09:06
  • @Stephan: Usually there's *something* at the top level which will log the error before the process terminates... at which point you'll have a stack trace. The exact details depend on the application. (For a console application, it just happens automatically, for example - just logging to stderr.) – Jon Skeet Jan 22 '22 at 09:10
5

It boils down to the different types of exceptions there actually are.

Checked exceptions (that is, exception classes that extend Exception) are typically errors you can recover from.

Unchecked exceptions (that is, exception classes that explicitly extend RuntimeException) are those that indicate an error in either expected behavior or program state. You wouldn't get a NullPointerException if the state of an object wasn't null when you dereferenced it, of course.

Blanket-catching everything - either Exception or Throwable, which is far worse - is not a good practice because you're assuming that you can recover from any exceptional behavior. There are some cases in which you shouldn't, or realistically can't (i.e. OutOfMemoryError for catch(Throwable t)). Further, catching runtime exceptions indicates a code smell; it means that you're covering up a coding error.

Be explicit about what it is you're catching.

Aside: Yes, catch Exception will also catch RuntimeException, since Exception is a superclass of RuntimeException. Just the same, Throwable will catch Exception and Error, which is why it's worse to write catch(Throwable t).

Makoto
  • 104,088
  • 27
  • 192
  • 230
  • "Be explicit about what it is you're catching." Why though? I don't think this is good programming advice. If you are modeling a class and you want it to never propagate an exception up, catching all `Exceptions` is perfectly fine. (I agree catching Throwable is no good). – frankelot May 21 '21 at 14:55
  • By leaving `Error` instances bubble up, how do we know which component will catch them ? How will this or those component(s) log those errors ? How do we know what happened once the program crashed due to an error ? Some errors can be difficult to reproduce. – Stephan Jan 22 '22 at 09:06
  • @Stephan: You don't have enough memory to catch an `OutOfMemoryError` so who *cares* what tries to catch it?? – Makoto Jan 22 '22 at 23:51
4

Throwable is super class of all Exception checked and unchecked(RuntimeException) and error.

java.lang.Object
     java.lang.Throwable
          java.lang.Exception
               java.lang.RuntimeException
          java.lang.Error

Ideally catching error is not a good practice.

And as RuntimeException extends Exception so it catches all RuntimeExcption's.

Subhrajyoti Majumder
  • 40,646
  • 13
  • 77
  • 103