Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Re-throwing RuntimeExceptions after catching Checked Exceptions [duplicate]

In Java it is observed that there is a convention of re-throwing a RuntimeException just after handling a Checked Exception.

This way has both good and bad consequences. When the compiler forces something to be handled via a Checked Exception, the developer can just get rid of it by catching it and re-throwing it as a RuntimeException.

Can someone explain if this scenario can be considered as a good practice? If so, would this approach be less error prone or would it make the code base unstable?

like image 839
MCF Avatar asked May 28 '13 14:05

MCF


People also ask

Is it good practice to throw exception in catch block?

It's fine practice to throw in the catch block. It's questionable practice to do so ignoring the original exception.

Is it good practice to throw RuntimeException?

Generally speaking, do not throw a RuntimeException or create a subclass of RuntimeException simply because you don't want to be bothered with specifying the exceptions your methods can throw.

Can we catch and throw the same exception?

Generally, you catch many exceptions, generalize them into one and throw it.. So that all similar exceptions can be handled in the same way..

Can runtime exception catch IOException?

Because IOException is a Checked Exception, which should be either handled or declared to be thrown. On contrary, RuntimeException is an Unchecked Exception.


2 Answers

Actually it is the incompetent attempts at handling checked exceptions which result in an unstable code base. Typically, you'll have this:

try {
   //stuff
} catch (IOException e) {
   log.error("Failed to do stuff", e);
   throw e;
}

and then next level up you'll have to deal with it again, typically logging it all over and making a mess of the log files. It will be even worse if you don't rethrow:

try {
   // do stuff
} catch (IOException e) {
  return null;
}

Now the calling code has no idea something went wrong, let alone what. Compared to those attempts, this actually accomplishes exactly what the application logic needs:

try {
  // do stuff
} catch (IOException e) {
  throw new RuntimeException(e);
}

Now the exception can freely propagate up the call stack until it reaches the well-defined exception barrier, where it:

  1. aborts the current unit of work;
  2. gets logged at a single, unified spot.

In a nutshell, to decide whether to catch-and-handle or catch-and-rethrow, just ask yourself this question:

Must the occurrence of this exception abort the current unit of work?

  • if yes: rethrow an unchecked exception;
  • if no: provide meaningful recovery code in the catch-block. (No, logging is not recovery).

From many years of real-life experience I can tell you that more than 90% of all possible checked exceptions are of the "aborting" type and need no handling at the place of occurrence.

Argument against the language feature of checked exceptions

Today, checked exceptions are widely recognized as a failed experiment in language design, and here's the key argument in a nutshell:

It is not up to the API creator to decide on the semantics of its exceptions in the client code.

Java's reasoning is that exceptions can be divided into

  1. exceptions resulting from programming errors (unchecked);
  2. exceptions due to circumstances outside of programmer's control (checked).

While this division may be real to some extent, it can be defined only from the perspective of client code. More to the point, it is not a very relevant division in practice: what truly matters is at what point the exception must be handled. If it is to be handled late, at the exception barrier, nothing is gained by the exception being checked. If handled early, then only sometimes there is a mild gain from checked exceptions.

Practice has confirmed that any gains afforded by checked exceptions are dwarfed by real-life damage done to real-life projects, as witnessed by every Java professional. Eclipse and other IDEs are to blame as well, suggesting inexperienced developers to wrap code in try-catch and then wonder what to write in the catch-block.

Whenever you encounter a method which throws Exception, you have found yet another living proof of the deficiency of checked exceptions.

like image 154
6 revs, 2 users 97% Avatar answered Nov 01 '22 03:11

6 revs, 2 users 97%


The idea of checked exceptions is "Java only" - as far as I know, no language after Java adopted this idea.

There are too many checked exceptions which are caught ... and silently ignored.

If you look at Scala, they dropped it as well - it's only there for Java compatibility.

In this tutorial on Oracle's web site, you will find this definition:

If a client can reasonably be expected to recover from an exception, make it a checked exception.
If a client cannot do anything to recover from the exception, make it an unchecked exception.

This notion has been adopted in Scala as well, and it works fine.

Technically speaking your proposal works. Discipline and code reviews are required in either way.

like image 35
Beryllium Avatar answered Nov 01 '22 03:11

Beryllium