Catching multiple exceptions in Java-8

JavaExceptionJava 8Try Catch

Java Problem Overview


While trying out the multi-catch feature I found in my m1() method everything is working fine as expected.

However, in m2() the same code does not compile. I have just changed the syntax to reduce the number of lines of code.

public class Main {

    public int m1(boolean bool) {
        try {
            if (bool) {
                throw new Excep1();
            }
            throw new Excep2();
            //This m1() is compiling  abs fine.
        } catch (Excep1 | Excep2 e) {
            return 0;
        }
    }

    public int m2(boolean b) {
        try {
            throw b ? new Excep1() : new Excep2();
            //This one is not compiling.
        } catch (Excep1 | Excep2 e) {
            return 0;
        }
    }

    private static interface I {
    }

    private static class Excep1 extends Exception implements I {
    }

    private static class Excep2 extends Exception implements I {
    }
}

Why doesn't method m2() compile?

Java Solutions


Solution 1 - Java

The type of the expression

b ? new Excep1() : new Excep2()

is Exception, since that's the common supertype of Excep1 and Excep2.

However, you are not catching Exception, so the compiler complains about it.

If you catch Exception, it will pass compilation:

public int m2(boolean b) {
    try {
        throw b ? new Excep1() : new Excep2();
    } catch (Exception e) {
        return 0;
    }
}

I tried to find the JLS entry that explains the type of conditional ternary expression in your example.

All I could find was that this particular expression is a 15.25.3. Reference Conditional Expression.

I'm not entirely sure if it counts as a poly expression or a standalone expression. I think it's standalone (since poly expressions involve an assignment context or an invocation context, and I don't think a throw statement counts as either of those).

For a standalone expression: "If the second and third operands have the same type (which may be the null type), then that is the type of the conditional expression."

In your case, the second and third operands have three common types - Object, Throwable and Exception - the type of the expression must be one of the latter two, since, "The Expression in a throw statement must either denote a variable or value of a reference type which is assignable (§5.2) to the type Throwable."

It appears that the compiler picks the most specific common type (Exception), and therefore a catch (Exception e) solves the compilation error.

I also tried to replace your two custom exceptions with two sub-classes of IOException, in which case catch (IOException e) solves the compilation error.

Solution 2 - Java

You're confusing the compiler with this line:

throw b ? new Excep1() : new Excep2();

The compiler sees that the result of the expression (to the right of the throw) is the common super class between Except1 and Except2, which is Exception, and therefore the effective type you are throwing becomes Exception. The catch statement cannot pick up that you're trying to throw Excep1 or Except2.

Solution 3 - Java

Java restrict you to catch or declare all exception types that method can throws,

It search for common parent for both (/all) Exceptions and expect you to catch or declare as throws, for example if Excep1 extends Throwable you will have to catch also Throwable

In first case Java is sure you are either throwing Excep1 or Excep2

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionSachin SachdevaView Question on Stackoverflow
Solution 1 - JavaEranView Answer on Stackoverflow
Solution 2 - JavaGideonleGrangeView Answer on Stackoverflow
Solution 3 - Javauser7294900View Answer on Stackoverflow