Generally speaking (for Java 6 and below), you should handle each exception individually...
try {
myObject.myMethod();
} catch (ExceptionA e) {
// Condition for A
} catch (ExceptionB e) {
// Condition for B
} catch (ExceptionC e) {
// Condition for C
}
This allows you to handle each exception differently based on what it is, but also means you are only handling those exceptions reported to be thrown by the method
In Java 7+ you can make use of "multi-catch" or "combined catch" (we can't find an "official" term)
try {
myObject.myMethod();
} catch (ExceptionA | ExceptionB | ExceptionC e) {
// Condition for A and B and C
}
But even then, you should be focusing exceptions into "common" use groups
try {
myObject.myMethod();
} catch (ExceptionA | ExceptionB e) {
// Condition for A and B
} catch (ExceptionC e) {
// Condition for C
}
Another option, if you control how the exceptions are defined, is to extend from a common base exception, a good example of this is the FileNotFoundException
which extends from the IOException
, which is thrown by FileReader
and FileInputStream
(as examples), this means you can handle the FileNotFoundException
as a common IOException
should you wish...
FileReader fr = null;
try {
fr = new FileReader(new File(...));
// Read from reader...
} catch (IOException exp) {
// Common catch block
} finally {
// Best attempt to close
try {
fr.close();
} catch (Exception exp) {
}
}
Or you could handle the FileNotFoundException
as it's own condition...
FileReader fr = null;
try {
fr = new FileReader(new File(...));
// Read from reader...
} catch (FileNotFoundException exp) {
// File not found condition
} catch (IOException exp) {
// Other IO condition
} finally {
// Best attempt to close
try {
if (fr != null) {
fr.close();
}
} catch (Exception exp) {
}
}
This allows you to either group "like" exceptions together, but also provides you with the control to define more fine grained conditions should you need to...
Beware though, we the above example, if I put the IOException
first, the FileNotFoundException
would never be handled, when doing this, make sure that you use the lowest/tightest/finest exceptions first, as they are processed sequentially in the order you have listed
Another option (which I'm not keen on, but have seen) might be to catch a "common" ancestor and then compare the actual type, which would allow you to provide common handlers for some sub-type of the exception.
} catch (IOException exp) {
if (exp instanceof FileNotFound || exp instanceof FileSystemException) {
// Common handling
} else {
// Generic handling
}
}
This might be helpful in situations where the method only throws the ancestor type (ie IOException
), but you need to provide a more fine grained resolution
But, again, I would be focused on only handling the expected "common" exceptions declared as been thrown, don't be tempered to catch Throwable
for example