我有一个这样的循环:

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


当前回答

如果你想在每个迭代中捕获Exception,或者检查哪个迭代抛出了Exception,并捕获迭代中的每个Exception,放置try…在循环内捕获。如果发生异常,这将不会中断循环,并且您可以在整个循环的每次迭代中捕获每个异常。

如果你想打破循环并在抛出异常时检查异常,请使用try…从循环中捕获。这将打破循环并在catch(如果有的话)之后执行语句。

这完全取决于你的需要。我更喜欢用try…如果Exception发生,结果不会有歧义,并且循环不会中断并完全执行。

其他回答

如果你想在每个迭代中捕获Exception,或者检查哪个迭代抛出了Exception,并捕获迭代中的每个Exception,放置try…在循环内捕获。如果发生异常,这将不会中断循环,并且您可以在整个循环的每次迭代中捕获每个异常。

如果你想打破循环并在抛出异常时检查异常,请使用try…从循环中捕获。这将打破循环并在catch(如果有的话)之后执行语句。

这完全取决于你的需要。我更喜欢用try…如果Exception发生,结果不会有歧义,并且循环不会中断并完全执行。

把它放在里面。您可以继续处理(如果您愿意),也可以抛出一个有用的异常,告诉客户端myString的值和包含坏值的数组的索引。我认为NumberFormatException已经告诉您坏的值,但原则是将所有有用的数据放在您抛出的异常中。考虑一下在程序的调试器中,您会对什么感兴趣。

考虑:

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

在需要的时候,您将非常感谢这样一个异常,其中包含尽可能多的信息。

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

性能:

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

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

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

我把0.02美元放进去。有时,您需要在稍后的代码中添加“finally”(因为谁会在第一次就写出完美的代码呢?)在这些情况下,将try/catch放在循环之外突然变得更有意义了。例如:

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

因为如果出现错误,您只希望释放一次数据库连接(或选择您最喜欢的其他资源类型……)。