I always try to reduce levels of nesting for readability and maintainability. If you have n try/catch blocks, each handling the same type of exception, why not refactor the code that can throw the exception into methods...it would look something like:
try {
firstBatchOfTricky();
secondBatchOfTricky();
....
nthBatchOfTricky();
} catch (ItWentBoomException e) {
// recover from boom
} catch (ItWentBangException e) {
// recover from bang
}
This is much more readable than having multiple try/catches. Note that your methods should describe what they do in the spirit of self documenting code.
Since you have your own Exception type, you can add the data you need to the exception to do different things in the catch block. When you say 'more specific message', you can just throw the exception with the detailed message; you shouldn't need multiple catch blocks. If you want to do drastically different things based on the state of the exception, just create more exception types and catch blocks but only one try block, as my pseudocode shows...
Finally, if you can't recover from the exception(s), you should not clutter the code with catch blocks. Throw a runtime exception and let it bubble. (Good advice from @tony in the comments)
Answer from hvgotcodes on Stack Overflowapex - What is an elegant way to catch multiple exceptions without catching generic exceptions? - Salesforce Stack Exchange
Catching Multiple Exceptions in a Single Catch Block in Java - LambdaTest Community
java - Best practice for handling many exceptions - Software Engineering Stack Exchange
Try Catch issue when trying to catch multiple exceptions
Could you please format your code properly, with all the indentations in place?
More on reddit.comVideos
I always try to reduce levels of nesting for readability and maintainability. If you have n try/catch blocks, each handling the same type of exception, why not refactor the code that can throw the exception into methods...it would look something like:
try {
firstBatchOfTricky();
secondBatchOfTricky();
....
nthBatchOfTricky();
} catch (ItWentBoomException e) {
// recover from boom
} catch (ItWentBangException e) {
// recover from bang
}
This is much more readable than having multiple try/catches. Note that your methods should describe what they do in the spirit of self documenting code.
Since you have your own Exception type, you can add the data you need to the exception to do different things in the catch block. When you say 'more specific message', you can just throw the exception with the detailed message; you shouldn't need multiple catch blocks. If you want to do drastically different things based on the state of the exception, just create more exception types and catch blocks but only one try block, as my pseudocode shows...
Finally, if you can't recover from the exception(s), you should not clutter the code with catch blocks. Throw a runtime exception and let it bubble. (Good advice from @tony in the comments)
This isn't a performance or personal preferences question: It's a functionality and requirements question.
Suppose I write:
Scenario 1:
try
{
doThingA();
}
catch (SomeException panic)
{
System.out.println("doThingA failed");
}
try
{
doThingB();
}
catch (SomeException panic)
{
System.out.println("doThingB failed");
}
Scenario 2:
try
{
doThingA();
doThingB();
}
catch (SomeException panic)
{
System.out.println("doThingA or doThingB failed");
}
These two scenarios are not equivalent: They do different things. In Scenario 1, if doThingA throws the exception, doThingB still executes. In Scenario 2, if doThingA throws the exception, doThingB is not executed. So the question is not which gives better performance or which is more readable code, but rather, if doThingA fails, should doThingB still be executed or not?
If what you really want is the second behavior, but you want different messages to tell the user what went wrong, then you should either throw different exceptions, or put the text of the message into the exception, i.e.
void doThingA() throws SomeException
{
... whatever code ...
if (theWorldIsAboutToEnd)
throw new SomeException("doThingA failed");
}
Then in the catch clause, instead of displaying a constant string, displayt SomeException.toString or SomeException.getMessage.
You can still support concrete types with getTypeName by using the Type.forName method.
Set<Type> allowlist = new Set<Type> { DmlException.class, ListException.class };
try
{
// do stuff
}
catch (Exception pokemon)
{
if (!allowlist.contains(Type.forName(pokemon.getTypeName()))
{
throw pokemon;
}
// actual error handling logic here
}
It's doable with an abstract base class as shown below.
public abstract class CustomException extends System.Exception {
}
Implementing exception classes
public class AException extends CustomException {
}
public class BException extends CustomException {
}
This test proves that it works
@IsTest
private class CustomException_Test {
@IsTest
private static void genericHandling() {
Boolean aCatched = false;
Boolean bCatched = false;
Boolean othersIgnored = true;
try {
throw new AException();
}
catch(CustomException cex) {
aCatched = true;
}
try {
throw new BException();
}
catch(CustomException cex) {
bCatched = true;
}
try {
throw new NotACustomException();
}
catch(CustomException cex) {
othersIgnored = false;
}
catch(Exception ex) {
othersIgnored = true;
}
System.assert(aCatched);
System.assert(bCatched);
System.assert(othersIgnored);
}
}