Can I catch multiple Java exceptions in the same catch clause?
Asked Answered
A

11

866

In Java, I want to do something like this:

try {
    ...     
} catch (/* code to catch IllegalArgumentException, SecurityException, 
            IllegalAccessException, and NoSuchFieldException at the same time */) {
   someCode();
}

...instead of:

try {
    ...     
} catch (IllegalArgumentException e) {
    someCode();
} catch (SecurityException e) {
    someCode();
} catch (IllegalAccessException e) {
    someCode();
} catch (NoSuchFieldException e) {
    someCode();
}

Is there any way to do this?

Aronoff answered 16/8, 2010 at 18:7 Comment(0)
P
1363

This has been possible since Java 7. The syntax for a multi-catch block is:

try { 
  ...
} catch (IllegalArgumentException | SecurityException | IllegalAccessException |
            NoSuchFieldException e) { 
  someCode();
}

Remember, though, that if all the exceptions belong to the same class hierarchy, you can simply catch that base exception type.

Also note that you cannot catch both ExceptionA and ExceptionB in the same block if ExceptionB is inherited, either directly or indirectly, from ExceptionA. The compiler will complain:

Alternatives in a multi-catch statement cannot be related by subclassing
  Alternative ExceptionB is a subclass of alternative ExceptionA

The fix for this is to only include the ancestor exception in the exception list, as it will also catch exceptions of the descendant type.

Phosphoprotein answered 16/8, 2010 at 18:11 Comment(12)
T.T - why redefine the bitwise or (|) operator? Why not use a comma, or the operator that has a more similar meaning, the logical or (||)?Winniewinnifred
@Winniewinnifred Maybe they thought it wouldn't matter anymore after they already had come up with the syntax for multiple bounds for generics.Eraeradiate
XOR sign ( I ) is not the same as OR ( || ), A | B means either A or B but not both A || B means either A or B or both so as for exceptions it is either exceptionA or exceptionB but not both at the same time. this is why they used XOR sing instead of OR and you can see that clearly when the exception is throws if you put 2 exceptions one of them is sub type of anotherPunchy
@Punchy in Java, bitwise XOR is ^ (caret) and bitwise OR is | (pipe) docs.oracle.com/javase/tutorial/java/nutsandbolts/op3.htmlSpital
It's worth mentioning that the type of an exception caught in multi-catch block is evalueted to the most derived common parentApostate
@Apostate not exactly. E.g. when you re-throw the exception, it will be handled as “either of the alternatives” rather than the common parent, i.e. you don’t need to put the parent into a throws clause.Luxurious
What type does the object "ex" have?Cannae
@Cannae It has the type which is thrown by the try block. For example, If IOException occurs, ex refers for IOException class.Scalariform
The choice of | for this is likely because it's the standard syntax for a union type in other languages. The language spec even calls it a "union", though it's only syntactically valid in this construct (as of Java 7): "An exception parameter may denote its type as either a single class type or a union of two or more class types (called alternatives). The alternatives of a union are syntactically separated by |." docs.oracle.com/javase/specs/jls/se7/html/jls-14.html#jls-14.20Chalky
Just a reminder, if you have to handle two exceptions differently where one is a subclass of another, ensure to have seperate Catch clases for the subclasses before the parent classes.Fulminous
... if all the exceptions belong to the same class hierarchy, you can simply catch that base exception type. Not really. Doing so, you will catch all other - and maybe unwanted - children of the base type. Sementically, this is different.Aleydis
“Remember, though, that if all the exceptions belong to the same class hierarchy, you can simply catch that base exception type.” That’s only true with sealed inheritance.Dionysiac
G
120

Not exactly before Java 7 but, I would do something like this:

Java 6 and before

try {
  //.....
} catch (Exception exc) {
  if (exc instanceof IllegalArgumentException || exc instanceof SecurityException || 
     exc instanceof IllegalAccessException || exc instanceof NoSuchFieldException ) {
    
     someCode();

  } else if (exc instanceof RuntimeException) {
     throw (RuntimeException) exc;     

  } else {
    throw new RuntimeException(exc);
  }

}

Java 7
try {
  //.....
} catch ( IllegalArgumentException | SecurityException |
         IllegalAccessException| NoSuchFieldException exc) {
  someCode();
}
Goral answered 28/8, 2012 at 9:15 Comment(9)
Note that your Java 6 example breaks the compiler's ability to tell what will be thrown from where.Marmawke
@Marmawke True, which is not [ so ] bad. You can always get the original exception with exc.getCause(). As a side note, Robert C. Martin (among others) recommends to use unchecked exceptions (the compiler has no idea of what kind of exception will be thrown from there); refer to Chapter 7: Error Handling on his book Clean code.Goral
In your Java 6 example shouldn't you be rethrowing the original exception instead of creating a new exception instance, i.e. throw exc instead of throw new RuntimeException(exc)?Indistinctive
Only if it is an instance of RuntimeException. I have updated the answer. =)Goral
This is pretty bad practice, from the perspective of readability.Murky
Instanceof operation is bit costly, it's better to avoid as much as possible.Signalment
@Goral This was awesomatic!Merwyn
Here in multi-catch approach, what would be the someCode() to expose which class has thrown the exception? As instanceof is bit costly like @ParameshKorrakuti mentioned, so not considerable.Ghastly
Exceptions are for exceptional cases. Exceptions are already expensive, instaceof being expensive shouldn't be a concern here...Goral
C
32

No, one per customer prior to Java 7.

You can catch a superclass, like java.lang.Exception, as long as you take the same action in all cases.

try {
    // some code
} catch(Exception e) { //All exceptions are caught here as all are inheriting java.lang.Exception
    e.printStackTrace();
}

But that might not be the best practice. You should only catch an exception when you have a strategy for actually handling it - and logging and rethrowing is not "handling it". If you don't have a corrective action, better to add it to the method signature and let it bubble up to someone that can handle the situation.

With JDK 7 and later you can do this:

try {
    ...     
} catch (IllegalArgumentException | SecurityException | IllegalAccessException | NoSuchFieldException e) {
    someCode();
}
Crawly answered 16/8, 2010 at 18:9 Comment(9)
Can I petition you to rephrase the portion about catching java.lang.Exception? I realize that it's an example, but I feel like some people might read this answer and say, "oh, okay, I'll just catch Exception then", when that's probably not what they want to (or should) do.Lamoreaux
I knew about that, but I don't want to do it... Oh, well, guess I'm stuck with 4 catches then, till the next version of Java...Aronoff
@duffymo: What's wrong with logging and rethrowing? Except that it clutters the code, its equivalent to not catching it, isn't it. Seen from the general error-handling strategy perspective. What's bad is logging and not rethrowing.Casemate
I don't consider logging and rethrowing handling anything. I'd prefer to let it bubble up to someone who can do something meaningful. That last layer where exceptions should never escape (e.g. controllers in a web app) should be the one to log the error in that case.Crawly
Am I the only one who finds it absurd that a log isn't automatically generated for me? It seems that we all have to write the same stupid logging message every time some piece of code might throw an exception.Winniewinnifred
Logging is the "hello world" of AOP. If it's that bothersome, write an aspect and be done with it once.Crawly
@ArtOfWarfare: Where would you like your logging? Either you catch the exception and really handle it and then a line like logger.log(e) is an negligible overhead or you add some informative message (which no generator can do for you). Or you don't catch it and then there's no reason to log it (as it happens elsewhere).Enrica
Your post should be a qualified comment, as it in no way answers the question posed here.Trumpet
Best way to destroy your exception handling purpose of code.Nessi
P
26

Within Java 7 you can define multiple catch clauses like:

catch (IllegalArgumentException | SecurityException e)
{
    ...
}
Pamphlet answered 16/8, 2010 at 18:12 Comment(0)
T
21

If there is a hierarchy of exceptions you can use the base class to catch all subclasses of exceptions. In the degenerate case you can catch all Java exceptions with:

try {
   ...
} catch (Exception e) {
   someCode();
}

In a more common case if RepositoryException is the the base class and PathNotFoundException is a derived class then:

try {
   ...
} catch (RepositoryException re) {
   someCode();
} catch (Exception e) {
   someCode();
}

The above code will catch RepositoryException and PathNotFoundException for one kind of exception handling and all other exceptions are lumped together. Since Java 7, as per @OscarRyz's answer above:

try { 
  ...
} catch( IOException | SQLException ex ) { 
  ...
}
Torrell answered 16/8, 2010 at 18:12 Comment(2)
BTW catch clauses are handled in order so if you put a parent exception class before a child class then it's never called eg: try { ... } catch (Exception e) { someCode(); } catch (RepositoryException re) { // never reached }Torrell
Actually precisely because it can never be reached, such code doesn't even compile.Herakleion
G
11

A cleaner (but less verbose, and perhaps not as preferred) alternative to user454322's answer on Java 6 (i.e., Android) would be to catch all Exceptions and re-throw RuntimeExceptions. This wouldn't work if you're planning on catching other types of exceptions further up the stack (unless you also re-throw them), but will effectively catch all checked exceptions.

For instance:

try {
    // CODE THAT THROWS EXCEPTION
} catch (Exception e) {
    if (e instanceof RuntimeException) {
        // this exception was not expected, so re-throw it
        throw e;
    } else {
        // YOUR CODE FOR ALL CHECKED EXCEPTIONS
    } 
}

That being said, for verbosity, it might be best to set a boolean or some other variable and based on that execute some code after the try-catch block.

Gorrian answered 18/10, 2013 at 21:4 Comment(1)
This approach prevents the compiler from determining whether or not a "catch block" will be reachable.Adagietto
T
4

In pre-7 how about:

  Boolean   caught = true;
  Exception e;
  try {
     ...
     caught = false;
  } catch (TransformerException te) {
     e = te;
  } catch (SocketException se) {
     e = se;
  } catch (IOException ie) {
     e = ie;
  }
  if (caught) {
     someCode(); // You can reference Exception e here.
  }
Tinsel answered 16/2, 2015 at 18:8 Comment(2)
wuold be a nice solution. How about to insert the final control of caught in a finally block?Secure
This requires more lines than the original question.Unison
B
4

For kotlin, it's not possible for now but they've considered to add it: Source
But for now, just a little trick:

try {
    // code
} catch(ex:Exception) {
    when(ex) {
        is SomeException,
        is AnotherException -> {
            // handle
        }
        else -> throw ex
    }
}
Bathelda answered 17/9, 2019 at 19:48 Comment(0)
K
4

It is very simple:

try { 
  // Your code here.
} catch (IllegalArgumentException | SecurityException | IllegalAccessException |
            NoSuchFieldException e) { 
  // Handle exception here.
}
Korrie answered 20/1, 2021 at 12:24 Comment(0)
D
0

Catch the exception that happens to be a parent class in the exception hierarchy. This is of course, bad practice. In your case, the common parent exception happens to be the Exception class, and catching any exception that is an instance of Exception, is indeed bad practice - exceptions like NullPointerException are usually programming errors and should usually be resolved by checking for null values.

Display answered 16/8, 2010 at 18:10 Comment(0)
B
-2

in Kotlin, this way can be useful:

var result = false
       
            try { ...
                   result=false

                    }catch (ex:Exception ){

                when (ex) {
                    is SocketTimeoutException,
                    is NetworkOnMainThreadException,
                    is UnknownHostException,
                    is IllegalThreadStateException -> result=false
                    else -> throw ex
                }
                
                 }
Bifrost answered 23/4, 2023 at 17:31 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.