120

I need to catch two exceptions because they require the same handling logic. I would like to do something like:

catch (Exception e, ExtendsRuntimeException re) {
    // common logic to handle both exceptions
}

Is it possible to avoid duplicating the handler code in each catch block?

John Watts
  • 8,717
  • 1
  • 31
  • 35
user710818
  • 23,228
  • 58
  • 149
  • 207
  • 4
    Have a look at http://docs.oracle.com/javase/7/docs/technotes/guides/language/enhancements.html#javase7 for more Java 7 enhancements. I'm a little surprised this question and it's answers received so many up votes. – Sridhar Jun 27 '12 at 09:02

6 Answers6

228

Java 7 and later

Multiple-exception catches are supported, starting in Java 7.

The syntax is:

try {
     // stuff
} catch (Exception1 | Exception2 ex) {
     // Handle both exceptions
}

The static type of ex is the most specialized common supertype of the exceptions listed. There is a nice feature where if you rethrow ex in the catch, the compiler knows that only one of the listed exceptions can be thrown.


Java 6 and earlier

Prior to Java 7, there are ways to handle this problem, but they tend to be inelegant, and to have limitations.

Approach #1

try {
     // stuff
} catch (Exception1 ex) {
     handleException(ex);
} catch (Exception2 ex) {
     handleException(ex);
}

public void handleException(SuperException ex) {
     // handle exception here
}

This gets messy if the exception handler needs to access local variables declared before the try. And if the handler method needs to rethrow the exception (and it is checked) then you run into serious problems with the signature. Specifically, handleException has to be declared as throwing SuperException ... which potentially means you have to change the signature of the enclosing method, and so on.

Approach #2

try {
     // stuff
} catch (SuperException ex) {
     if (ex instanceof Exception1 || ex instanceof Exception2) {
         // handle exception
     } else {
         throw ex;
     }
}

Once again, we have a potential problem with signatures.

Approach #3

try {
     // stuff
} catch (SuperException ex) {
     if (ex instanceof Exception1 || ex instanceof Exception2) {
         // handle exception
     }
}

If you leave out the else part (e.g. because there are no other subtypes of SuperException at the moment) the code becomes more fragile. If the exception hierarchy is reorganized, this handler without an else may end up silently eating exceptions!

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
  • If this is the case, how will the resulting catch block handle functions which are unique to a particular type of exception? For example `ex.functionFromExceptionType2()` vs `ex.functionFromExceptionType1()` – Peaches491 Jun 26 '12 at 19:27
  • @Peaches491 (1) the vast majority of Exceptions have the exact same set of methods; (2) if u want different behavior for `Type1` and `Type2` then u can not use this construct. – emory Jun 26 '12 at 19:32
  • I figured as much. Just thought I'd ask to be certain – Peaches491 Jun 26 '12 at 19:34
  • 2
    @emory I might be wrong, but Exceptions are objects. So can't you use the `instanceof` function to see of your exception object is of one type or another inside of the catch statement? So you could catch, do common code, and then have if blocks with `instanceof` to do the code that would be different. – Sephallia Jun 26 '12 at 21:25
  • @Sephallia U r right. It seems backwards, but u could use casting inside the catch statement. – emory Jun 26 '12 at 22:18
  • @emory - It only seems backwards if you don't think of exceptions as objects :-) – Stephen C Apr 22 '14 at 23:37
  • Its great for tests. I use it for: `catch (AssertionError | Exception ex)` – Krzysztof Walczewski May 22 '18 at 08:35
34

Java <= 6.x just allows you to catch one exception for each catch block:

try {

} catch (ExceptionType name) {

} catch (ExceptionType name) {

}

Documentation:

Each catch block is an exception handler and handles the type of exception indicated by its argument. The argument type, ExceptionType, declares the type of exception that the handler can handle and must be the name of a class that inherits from the Throwable class.

For Java 7 you can have multiple Exception caught on one catch block:

catch (IOException|SQLException ex) {
    logger.log(ex);
    throw ex;
}

Documentation:

In Java SE 7 and later, a single catch block can handle more than one type of exception. This feature can reduce code duplication and lessen the temptation to catch an overly broad exception.

Reference: http://docs.oracle.com/javase/tutorial/essential/exceptions/catch.html

egerardus
  • 11,316
  • 12
  • 80
  • 123
Francisco Spaeth
  • 23,493
  • 7
  • 67
  • 106
12

If you aren't on java 7, you can extract your exception handling to a method - that way you can at least minimize duplication

try {
   // try something
}
catch(ExtendsRuntimeException e) { handleError(e); }
catch(Exception e) { handleError(e); }
jeff
  • 4,325
  • 16
  • 27
  • 1
    Good answer +1. The sample code does not make sense. If ur naming conventions are any good then `ExtendsRuntimeException` is an `Exception`. So there is no need for the first catch block. A better sample would be catch(RuntimeExceptionA e ) { handleAB( e ) ; } catch ( RuntimeExceptionB e ) { handleAB ( e ) ; } catch ( RuntimeExceptionC e ) { handleC ( e ) ; }` It is not possible to collapse them all into `catch ( RuntimeException e )`. – emory Jun 26 '12 at 18:13
  • This approach may be necessary even with java 7. For example, if you want to treat `IndexOutOfBoundException` and (non `RuntimeException`) `Throwable` the same but want to treat (non `IndexOutOfBoundsException`) `RuntimeException` differently, then the new Java 7 syntax is not useful. – emory Jun 26 '12 at 18:56
2

For Java < 7 you can use if-else along with Exception:

try {
    // common logic to handle both exceptions
} catch (Exception ex) {
    if (ex instanceof Exception1 || ex instanceof Exception2) {

    }
    else {
        throw ex;
        // or if you don't want to have to declare Exception use
        // throw new RuntimeException(ex);
    }
}

Edited and replaced Throwable with Exception.

Sarel Botha
  • 12,419
  • 7
  • 54
  • 59
  • 1
    I think this is more readable then jeff's answer – Daniel Serodio Jun 26 '12 at 19:05
  • 2
    You should avoid catching overly-broad Exceptions, which is what motivated the Java 7 change. Moreover you should never catch things that you are unable to deal with. Finally, you should never catch Errors, and thus you should never catch the wider Throwable either. – OrangeDog Jun 26 '12 at 20:58
2

http://docs.oracle.com/javase/tutorial/essential/exceptions/catch.html covers catching multiple exceptions in the same block.

 try {
     // your code
} catch (Exception1 | Exception2 ex) {
     // Handle 2 exceptions in Java 7
}

I'm making study cards, and this thread was helpful, just wanted to put in my two cents.

Eli
  • 39
  • 2
  • 2
    Your answer is 6 months late and doesn't add anything new. In cases like this, it's better to simply upvote the answer that has the info you find useful. – james.garriss Sep 10 '13 at 16:45
2

Before the launch of Java SE 7 we were habitual of writing code with multiple catch statements associated with a try block. A very basic Example:

 try {
  // some instructions
} catch(ATypeException e) {
} catch(BTypeException e) {
} catch(CTypeException e) {
}

But now with the latest update on Java, instead of writing multiple catch statements we can handle multiple exceptions within a single catch clause. Here is an example showing how this feature can be achieved.

try {
// some instructions
} catch(ATypeException|BTypeException|CTypeException ex) {
   throw e;
}

So multiple Exceptions in a single catch clause not only simplifies the code but also reduce the redundancy of code. I found this article which explains this feature very well along with its implementation. Improved and Better Exception Handling from Java 7 This may help you too.

Saurab Parakh
  • 1,054
  • 3
  • 12
  • 19
  • Your answer was 18 months late and didn't add anything new. In cases like this, it's better to simply upvote the answer that has the info you find useful. – Stephen C Mar 07 '18 at 03:07