我有一个这样的循环:

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


当前回答

As already mentioned, the performance is the same. However, user experience isn't necessarily identical. In the first case, you'll fail fast (i.e. after the first error), however if you put the try/catch block inside the loop, you can capture all the errors that would be created for a given call to the method. When parsing an array of values from strings where you expect some formatting errors, there are definitely cases where you'd like to be able to present all the errors to the user so that they don't need to try and fix them one by one.

其他回答

我想添加我自己的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).

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

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

这取决于故障处理。如果你只是想跳过error元素,请尝试内部:

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

在任何其他情况下,我宁愿到外面去试试。代码更可读,更干净。如果返回null,在错误情况下抛出一个IllegalArgumentException可能会更好。

你应该喜欢外面的版本而不是里面的版本。这只是规则的一个特定版本,将任何可以移动到循环外的东西移动到循环外。根据IL编译器和JIT编译器的不同,您的两个版本最终可能具有不同的性能特征,也可能没有。

另一方面,你可能应该看看float。TryParse或Convert.ToFloat。