Should try…catch go inside or outside a loop?

后端 未结 21 1736
眼角桃花
眼角桃花 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:43

    put it inside. You can keep processing (if you want) or you can throw a helpful exception that tells the client the value of myString and the index of the array containing the bad value. I think NumberFormatException will already tell you the bad value but the principle is to place all the helpful data in the exceptions that you throw. Think about what would be interesting to you in the debugger at this point in the program.

    Consider:

    try {
       // parse
    } catch (NumberFormatException nfe){
       throw new RuntimeException("Could not parse as a Float: [" + myString + 
                                  "] found at index: " + i, nfe);
    } 
    

    In the time of need you will really appreciate an exception like this with as much information in it as possible.

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

    In your examples there is no functional difference. I find your first example more readable.

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

    That depends on the failure handling. If you just want to skip the error elements, try inside:

    for(int i = 0; i < max; i++) {
        String myString = ...;
        try {
            float myNum = Float.parseFloat(myString);
            myFloats[i] = myNum;
        } catch (NumberFormatException ex) {
            --i;
        }
    }
    

    In any other case i would prefer the try outside. The code is more readable, it is more clean. Maybe it would be better to throw an IllegalArgumentException in the error case instead if returning null.

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

    I'll put my $0.02 in. Sometimes you wind up needing to add a "finally" later on in your code (because who ever writes their code perfectly the first time?). In those cases, suddenly it makes more sense to have the try/catch outside the loop. For example:

    try {
        for(int i = 0; i < max; i++) {
            String myString = ...;
            float myNum = Float.parseFloat(myString);
            dbConnection.update("MY_FLOATS","INDEX",i,"VALUE",myNum);
        }
    } catch (NumberFormatException ex) {
        return null;
    } finally {
        dbConnection.release();  // Always release DB connection, even if transaction fails.
    }
    

    Because if you get an error, or not, you only want to release your database connection (or pick your favorite type of other resource...) once.

    0 讨论(0)
  • All right, after Jeffrey L Whitledge said that there was no performance difference (as of 1997), I went and tested it. I ran this small benchmark:

    public class Main {
    
        private static final int NUM_TESTS = 100;
        private static int ITERATIONS = 1000000;
        // time counters
        private static long inTime = 0L;
        private static long aroundTime = 0L;
    
        public static void main(String[] args) {
            for (int i = 0; i < NUM_TESTS; i++) {
                test();
                ITERATIONS += 1; // so the tests don't always return the same number
            }
            System.out.println("Inside loop: " + (inTime/1000000.0) + " ms.");
            System.out.println("Around loop: " + (aroundTime/1000000.0) + " ms.");
        }
        public static void test() {
            aroundTime += testAround();
            inTime += testIn();
        }
        public static long testIn() {
            long start = System.nanoTime();
            Integer i = tryInLoop();
            long ret = System.nanoTime() - start;
            System.out.println(i); // don't optimize it away
            return ret;
        }
        public static long testAround() {
            long start = System.nanoTime();
            Integer i = tryAroundLoop();
            long ret = System.nanoTime() - start;
            System.out.println(i); // don't optimize it away
            return ret;
        }
        public static Integer tryInLoop() {
            int count = 0;
            for (int i = 0; i < ITERATIONS; i++) {
                try {
                    count = Integer.parseInt(Integer.toString(count)) + 1;
                } catch (NumberFormatException ex) {
                    return null;
                }
            }
            return count;
        }
        public static Integer tryAroundLoop() {
            int count = 0;
            try {
                for (int i = 0; i < ITERATIONS; i++) {
                    count = Integer.parseInt(Integer.toString(count)) + 1;
                }
                return count;
            } catch (NumberFormatException ex) {
                return null;
            }
        }
    }
    

    I checked the resulting bytecode using javap to make sure that nothing got inlined.

    The results showed that, assuming insignificant JIT optimizations, Jeffrey is correct; there is absolutely no performance difference on Java 6, Sun client VM (I did not have access to other versions). The total time difference is on the order of a few milliseconds over the entire test.

    Therefore, the only consideration is what looks cleanest. I find that the second way is ugly, so I will stick to either the first way or Ray Hayes's way.

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

    If you want to catch Exception for each iteration, or check at what iteration Exception is thrown and catch every Exceptions in an itertaion, place try...catch inside the loop. This will not break the loop if Exception occurs and you can catch every Exception in each iteration throughout the loop.

    If you want to break the loop and examine the Exception whenever thrown, use try...catch out of the loop. This will break the loop and execute statements after catch (if any).

    It all depends on your need. I prefer using try...catch inside the loop while deploying as, if Exception occurs, the results aren't ambiguous and loop will not break and execute completely.

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