Should try…catch go inside or outside a loop?

后端 未结 21 1737
眼角桃花
眼角桃花 2020-11-30 17:33

I have a loop that looks something like this:

for (int i = 0; i < max; i++) {
    String myString = ...;
    float myNum = Float.parseFloat(myString);
            


        
相关标签:
21条回答
  • 2020-11-30 17:54

    While performance might be the same and what "looks" better is very subjective, there is still a pretty big difference in functionality. Take the following example:

    Integer j = 0;
        try {
            while (true) {
                ++j;
    
                if (j == 20) { throw new Exception(); }
                if (j%4 == 0) { System.out.println(j); }
                if (j == 40) { break; }
            }
        } catch (Exception e) {
            System.out.println("in catch block");
        }
    

    The while loop is inside the try catch block, the variable 'j' is incremented until it hits 40, printed out when j mod 4 is zero and an exception is thrown when j hits 20.

    Before any details, here the other example:

    Integer i = 0;
        while (true) {
            try {
                ++i;
    
                if (i == 20) { throw new Exception(); }
                if (i%4 == 0) { System.out.println(i); }
                if (i == 40) { break; }
    
            } catch (Exception e) { System.out.println("in catch block"); }
        }
    

    Same logic as above, only difference is that the try/catch block is now inside the while loop.

    Here comes the output (while in try/catch):

    4
    8
    12 
    16
    in catch block
    

    And the other output (try/catch in while):

    4
    8
    12
    16
    in catch block
    24
    28
    32
    36
    40
    

    There you have quite a significant difference:

    while in try/catch breaks out of the loop

    try/catch in while keeps the loop active

    0 讨论(0)
  • 2020-11-30 17:54

    You should prefer the outer version over the inner version. This is just a specific version of the rule, move anything outside the loop that you can move outside the loop. Depending on the IL compiler and JIT compiler your two versions may or may not end up with different performance characteristics.

    On another note you should probably look at float.TryParse or Convert.ToFloat.

    0 讨论(0)
  • 2020-11-30 18:00

    Another aspect not mentioned in the above is the fact that every try-catch has some impact on the stack, which can have implications for recursive methods.

    If method "outer()" calls method "inner()" (which may call itself recursively), try to locate the try-catch in method "outer()" if possible. A simple "stack crash" example we use in a performance class fails at about 6,400 frames when the try-catch is in the inner method, and at about 11,600 when it is in the outer method.

    In the real world, this can be an issue if you're using the Composite pattern and have large, complex nested structures.

    0 讨论(0)
  • 2020-11-30 18:01

    As already mentioned, the performance is the same. However, user experience isn't necessarily identical. In the first case, you'll fail fast (i.e. after the first error), however if you put the try/catch block inside the loop, you can capture all the errors that would be created for a given call to the method. When parsing an array of values from strings where you expect some formatting errors, there are definitely cases where you'd like to be able to present all the errors to the user so that they don't need to try and fix them one by one.

    0 讨论(0)
  • 2020-11-30 18:01

    setting up a special stack frame for the try/catch adds additional overhead, but the JVM may be able to detect the fact that you're returning and optimize this away.

    depending on the number of iterations, performance difference will likely be negligible.

    However i agree with the others that having it outside the loop make the loop body look cleaner.

    If there's a chance that you'll ever want to continue on with the processing rather than exit if there an invalid number, then you would want the code to be inside the loop.

    0 讨论(0)
  • 2020-11-30 18:03

    PERFORMANCE:

    There is absolutely no performance difference in where the try/catch structures are placed. Internally, they are implemented as a code-range table in a structure that is created when the method is called. While the method is executing, the try/catch structures are completely out of the picture unless a throw occurs, then the location of the error is compared against the table.

    Here's a reference: http://www.javaworld.com/javaworld/jw-01-1997/jw-01-hood.html

    The table is described about half-way down.

    0 讨论(0)
提交回复
热议问题