开发者

Multiple or Single Try Catch [duplicate]

开发者 https://www.devze.com 2023-02-01 09:50 出处:网络
This question already has answers here: Multiple try-catch or one? (11 answers) Closed 2 years ago. I\'m working on cleaning up some of my code and I came to a point where I wasn\'t sure
This question already has answers here: Multiple try-catch or one? (11 answers) Closed 2 years ago.

I'm working on cleaning up some of my code and I came to a point where I wasn't sure which route would be better.

Currently I have a single try catch block over the majority of my method and it handles a few separate exceptions at the end, but I figured having more try catch blocks would be better just for maintenance. However, while breaking down the code I came to a point where I was writing multiple blocks for the same type of exception. I can see the up side to writing a block for each part since I can then give more specifics to why it failed.

My question is this... is there a downside to doing this? Could there be performance issues or some other hidden monster that I'm not seeing?

Also, what is the preferred way of handling multiple exceptions in a method, is there an industry stand开发者_运维技巧ard?

Just to better illustrate my point here's some pseudo code

//multiple try catch for same exception
try {
     //some code here
} catch (MyException e) {
     //specific error message here
}
try {
     //some different code here
} catch (MyException e) {
     //more specific error message indicating a different issue
}


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.


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)


If the exceptions can be handled differently (different error message, etc.) then catching them separately is fine.

If the Exception types are different, that doesn't mean you have to have separate try blocks, you can have one try block with multiple catches.


It's totally dependent on the scenario. If you do a bunch of stuff that throws a security exception and you handle that scenario the same way, you can use a try block for that.

However, having said that, using many smaller try/catch blocks is often better in my opinion. Using a big try/catch is like using several goto statements except you can't tell where the gotos are coming from.

Eg in the below how can you tell which method would go to exception1 and which would go to exception 2? It's fine if it's a small block but once it gets bigger, it becomes very unreadable.

try{
  doThing1();
  doThing2();
  doThing3();
  doThing4();
  doThing5();
  doThing6();
  doThing7();
  doThing8();
  doThing9();
} catch (Exception1 e){

} catch (Exception2 e){

}

Below is clearer.

try{
  doThing1();      
} catch (Exception1 e){ [...] } 
  doThing2();
  doThing3();
  doThing4();
  doThing5();
  doThing6();
  doThing7();
  doThing8();
try{
    doThing9();
} catch (Exception2 e){ [...] }


My personal preference is a single try that may or may not have multiple catch blocks. My methods tend to be small enough where this makes sense. If yours are getting too long for that to be practical, perhaps you need to think about refactoring.

One thing about catch blocks: If your catch block prints or logs the stack trace and re-throws, I'd say that you would be better off adding the exception to the throws clause in the method signature and let it bubble up.


I agree with the general consensus of the above answers, that a single try-catch block is better. However, by the time your method is long enough to have you looking at this question, it's probably too long. And it may be easier to extract new methods from it if the exception handling is more localized. Still, I think your best bet may be to extract methods that simply throw the exception and leave the exception handling in place, in the original method - ideally in a single try-catch block.


It looks very old question. But, my answer would make it relavent because in the recent days Java 7 has added new feature to add multiple exaceptions and the catch block. This would eliminate the lot of code and looks very interesting. I come across this link explianing about the try-with-resource concept.


Excellent question. I'm going to say that you should use a single try-catch block. My reasoning: if you have reason to partition your method into multiple try-catch blocks, you should probably be thinking about refactoring your method into multiple methods, each with its own single try-catch block.


I try to avoid repeating code whenever possible. So if the response to a certain type of exception is the same then catch it once.


I prefer single try-catch block. If the length of the method is grows a lot then I prefer to divide the method into multiple internal methods for modularity puporse.
Also at times you might be able to re-use these internal methods.
I feel this way its much cleaner and better for maintainence.


It depends on your code logic - can you interrupt your process (calculation or whatever) at any moment or you can/should/need/must control flow and rollback/notify/verify/whateverify if some error condition is indicated by exception at particular step.

If you are implementing simple RSS client, you can keep all socket-related code in one block. But if you are writing bittorrent client, you will need state machine and much more granulated exception handling.


To be safe always use individual try catch blocks for every exception throwing statement because if you write all in one try block then if any statement throws an exception then statements written below it will not be executed.


I can see that every answer to this question is good, but no one is using the concept of Hierarchy in java. You don't need to be specific with catching any exception if you use:

try {

    //your code

}
catch(Exception e) {

    System.println(e.getCause());

}

You are catching all exceptions like this, since all the other exceptions are extending the abstract class Exception … so any exception will be caught!

I hope this helps to clear the picture.

0

精彩评论

暂无评论...
验证码 换一张
取 消