Mukund Gandlur
Mukund Gandlur

Reputation: 869

Suppressed exceptions in Java

Consider the below example.

    public static void main(String[] args) {

        try{
            throw new NullPointerException();
        } finally{
           throw new ClassCastException();
        }

    }

This throws a ClassCastException only and the NullPointerException is suppressed. And this is possible in Java SE6 too. Then why are Suppressed Exceptions stressed upon only in JavaSE7. What is it that I am missing here?

Upvotes: 2

Views: 2723

Answers (2)

Stephen C
Stephen C

Reputation: 719709

How is it different from this? Isn't it just 2 exceptions thrown with the latest one suppressing the previous one.

What you are actually doing is better described as "replacing" on exception with another. (Or more precisely, discarding the first exception and throwing the second exception unconditionally!)

Exception suppression (as the JLS uses the term) is different in the following respects:

  1. Normal suppression happens (automatically) only to exceptions that are thrown in a try-with-resources, during resource cleanup by the try-with-resources. What you are doing in your example happens to any / all exceptions, irrespective of their origin.

  2. With normal suppression, the secondary exception is suppressed. In this case the primary exception is being "suppressed".

  3. With normal suppression, the suppressed exception is recorded in the original exception. In your example, it is discarded.


Now, admittedly, you could use the Throwable.addSuppressedException(...) method by hand in other ways. I'm describing how it is intended to be used.

Upvotes: 6

Gernot
Gernot

Reputation: 384

This behaviour can be explained by citing the the Java Specification, Section 14.20.2:

  • A try statement with a finally block is executed by first executing the try block. Then there is a choice:
  • ... (leaving out the happy path)
  • If the run-time type of V is not assignment compatible with a catchable exception class of any catch clause of the try statement, then the finally block is executed. Then there is a choice:
  • If the finally block completes normally, then the try statement completes abruptly because of a throw of the value V.
  • If the finally block completes abruptly for reason S, then the try statement completes abruptly for reason S (and the throw of value V is discarded and forgotten).

This exactly describes the situation in your code sample.

  • First the statement within the try block is executed (throwing a NullPointerException)
  • The run type of the thrown Exception (NullPointerException) is not assignment compatible with a catchable exception class of any catch clause for this try statement, i.e. there is no catch statement for a NullPointerException
  • Then the finally block is executed and a ClassCastException is thrown
  • As the finally statement has completed abruptly (for the ClassCastException), the try statement completes abruptly (for the exception that caused the abruption of the finally block: the ClassCastException). The throw of the NullPointerException is discarded and forgotten.

Upvotes: 0

Related Questions