Should try…catch go inside or outside a loop?

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

    I's like to add my own 0.02c about two competing considerations when looking at the general problem of where to position exception handling:

    1. The "wider" the responsibility of the try-catch block (i.e. outside the loop in your case) means that when changing the code at some later point, you may mistakenly add a line which is handled by your existing catch block; possibly unintentionally. In your case, this is less likely because you are explicitly catching a NumberFormatException

    2. The "narrower" the responsibility of the try-catch block, the more difficult refactoring becomes. Particularly when (as in your case) you are executing a "non-local" instruction from within the catch block (the return null statement).

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

    Performance: as Jeffrey said in his reply, in Java it doesn't make much difference.

    Generally, for readability of the code, your choice of where to catch the exception depends upon whether you want the loop to keep processing or not.

    In your example you returned upon catching an exception. In that case, I'd put the try/catch around the loop. If you simply want to catch a bad value but carry on processing, put it inside.

    The third way: You could always write your own static ParseFloat method and have the exception handling dealt with in that method rather than your loop. Making the exception handling isolated to the loop itself!

    class Parsing
    {
        public static Float MyParseFloat(string inputValue)
        {
            try
            {
                return Float.parseFloat(inputValue);
            }
            catch ( NumberFormatException e )
            {
                return null;
            }
        }
    
        // ....  your code
        for(int i = 0; i < max; i++) 
        {
            String myString = ...;
            Float myNum = Parsing.MyParseFloat(myString);
            if ( myNum == null ) return;
            myFloats[i] = (float) myNum;
        }
    }
    
    0 讨论(0)
  • 2020-11-30 17:53

    I agree with all the performance and readability posts. However, there are cases where it really does matter. A couple other people mentioned this, but it might be easier to see with examples.

    Consider this slightly modified example:

    public static void main(String[] args) {
        String[] myNumberStrings = new String[] {"1.2345", "asdf", "2.3456"};
        ArrayList asNumbers = parseAll(myNumberStrings);
    }
    
    public static ArrayList parseAll(String[] numberStrings){
        ArrayList myFloats = new ArrayList();
    
        for(int i = 0; i < numberStrings.length; i++){
            myFloats.add(new Float(numberStrings[i]));
        }
        return myFloats;
    }
    

    If you want the parseAll() method to return null if there are any errors (like the original example), you'd put the try/catch on the outside like this:

    public static ArrayList parseAll1(String[] numberStrings){
        ArrayList myFloats = new ArrayList();
        try{
            for(int i = 0; i < numberStrings.length; i++){
                myFloats.add(new Float(numberStrings[i]));
            }
        } catch (NumberFormatException nfe){
            //fail on any error
            return null;
        }
        return myFloats;
    }
    

    In reality, you should probably return an error here instead of null, and generally I don't like having multiple returns, but you get the idea.

    On the other hand, if you want it to just ignore the problems, and parse whatever Strings it can, you'd put the try/catch on the inside of the loop like this:

    public static ArrayList parseAll2(String[] numberStrings){
        ArrayList myFloats = new ArrayList();
    
        for(int i = 0; i < numberStrings.length; i++){
            try{
                myFloats.add(new Float(numberStrings[i]));
            } catch (NumberFormatException nfe){
                //don't add just this one
            }
        }
    
        return myFloats;
    }
    
    0 讨论(0)
  • 2020-11-30 17:53

    If its an all-or-nothing fail, then the first format makes sense. If you want to be able to process/return all the non-failing elements, you need to use the second form. Those would be my basic criteria for choosing between the methods. Personally, if it is all-or-nothing, I wouldn't use the second form.

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

    If you put the try/catch inside the loop, you'll keep looping after an exception. If you put it outside the loop you'll stop as soon as an exception is thrown.

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

    The whole point of exceptions is to encourage the first style: letting the error handling be consolidated and handled once, not immediately at every possible error site.

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