我有一个这样的循环:

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中更干净,可能是在它自己的方法中。然而,关于哪个速度更快仍存在争议。有人能测试一下并给出一个统一的答案吗?


当前回答

异常的全部意义在于鼓励第一种风格:让错误处理被合并并处理一次,而不是在每个可能的错误位置立即处理。

其他回答

异常的全部意义在于鼓励第一种风格:让错误处理被合并并处理一次,而不是在每个可能的错误位置立即处理。

性能:

try/catch结构放置的位置绝对没有性能差异。在内部,它们被实现为调用方法时创建的结构中的代码范围表。当方法执行时,try/catch结构完全不在图中,除非发生抛出,然后将错误的位置与表进行比较。

这里有一个参考:http://www.javaworld.com/javaworld/jw-01-1997/jw-01-hood.html

这张桌子在一半的地方被描述。

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

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

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

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

如果这是一个全有或全无的失败,那么第一种格式是有意义的。如果希望能够处理/返回所有未失败的元素,则需要使用第二种形式。这些就是我选择方法的基本标准。就我个人而言,如果是孤注一掷,我不会使用第二种形式。

上面没有提到的另一个方面是,每个try-catch都会对堆栈产生一些影响,这可能会对递归方法产生影响。

如果方法"outer()"调用方法"inner()"(它可能递归地调用自己),如果可能的话,尝试在方法"outer()"中找到try-catch。我们在性能类中使用的一个简单的“堆栈崩溃”示例,当try-catch在内部方法中时,在大约6400帧时失败,当它在外部方法中时,在大约11,600帧时失败。

在现实世界中,如果您正在使用Composite模式并且具有大型、复杂的嵌套结构,这可能会成为一个问题。