我有一个这样的循环:

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

这是一个方法的主要内容,该方法的唯一目的是返回浮点数数组。我想让这个方法在出现错误时返回null,所以我把循环放在try…Catch block,像这样:

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

但后来我也想到试一试……Catch块在循环中,像这样:

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

是否有任何理由,性能或其他方面,更喜欢其中一个?


编辑:共识似乎是,将循环放在try/catch中更干净,可能是在它自己的方法中。然而,关于哪个速度更快仍存在争议。有人能测试一下并给出一个统一的答案吗?


当前回答

如果它在内部,那么您将获得N次try/catch结构的开销,而不是只在外部获得一次。


每次调用Try/Catch结构都会增加方法执行的开销。只需要处理结构所需的一点点内存和处理器节拍。如果运行一个循环100次,假设每个try/catch调用的代价是1 tick,那么在循环内执行try/catch调用的代价是100 tick,而在循环外只执行1 tick。

其他回答

As long as you are aware of what you need to accomplish in the loop you could put the try catch outside the loop. But it is important to understand that the loop will then end as soon as the exception occurs and that may not always be what you want. This is actually a very common error in Java based software. People need to process a number of items, such as emptying a queue, and falsely rely on an outer try/catch statement handling all possible exceptions. They could also be handling only a specific exception inside the loop and not expect any other exception to occur. Then if an exception occurs that is not handled inside the loop then the loop will be "preemted", it ends possibly prematurely and the outer catch statement handles the exception.

如果循环在生活中扮演清空队列的角色,那么循环很可能在队列真正清空之前就结束了。非常常见的错误。

My perspective would be try/catch blocks are necessary to insure proper exception handling, but creating such blocks has performance implications. Since, Loops contain intensive repetitive computations, it is not recommended to put try/catch blocks inside loops. Additionally, it seems where this condition occurs, it is often "Exception" or "RuntimeException" which is caught. RuntimeException being caught in code should be avoided. Again, if if you work in a big company it's essential to log that exception properly, or stop runtime exception to happen. Whole point of this description is PLEASE AVOID USING TRY-CATCH BLOCKS IN LOOPS

在你的例子中没有功能上的区别。我觉得你的第一个例子可读性更强。

我想添加我自己的0.02c,关于在哪里放置异常处理的一般问题时两个相互竞争的考虑因素:

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 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).

为try/catch设置一个特殊的堆栈框架会增加额外的开销,但是JVM可能能够检测到您正在返回并优化它。

根据迭代次数的不同,性能差异可能可以忽略不计。

然而,我同意其他人的观点,把它放在循环之外会让循环体看起来更干净。

如果您希望继续处理,而不是在存在无效数字时退出,那么您将希望代码位于循环中。