try...catch 应该进入循环内部还是外部?

新手上路,请多包涵

我有一个看起来像这样的循环:

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

这是一个方法的主要内容,其唯一目的是返回浮点数数组。如果出现错误,我希望此方法返回 null ,因此我将循环放在 try...catch 块中,如下所示:

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

但后来我也想到将 try...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 中更清晰,可能放在它自己的方法中。然而,关于哪个更快的问题仍然存在争论。有人可以对此进行测试并返回统一答案吗?

原文由 Michael Myers 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 495
2 个回答

好吧,在 Jeffrey L Whitledge 说 没有性能差异(截至 1997 年)之后,我就去测试了。我跑了这个小基准:

 public class Main {

    private static final int NUM_TESTS = 100;
    private static int ITERATIONS = 1000000;
    // time counters
    private static long inTime = 0L;
    private static long aroundTime = 0L;

    public static void main(String[] args) {
        for (int i = 0; i < NUM_TESTS; i++) {
            test();
            ITERATIONS += 1; // so the tests don't always return the same number
        }
        System.out.println("Inside loop: " + (inTime/1000000.0) + " ms.");
        System.out.println("Around loop: " + (aroundTime/1000000.0) + " ms.");
    }
    public static void test() {
        aroundTime += testAround();
        inTime += testIn();
    }
    public static long testIn() {
        long start = System.nanoTime();
        Integer i = tryInLoop();
        long ret = System.nanoTime() - start;
        System.out.println(i); // don't optimize it away
        return ret;
    }
    public static long testAround() {
        long start = System.nanoTime();
        Integer i = tryAroundLoop();
        long ret = System.nanoTime() - start;
        System.out.println(i); // don't optimize it away
        return ret;
    }
    public static Integer tryInLoop() {
        int count = 0;
        for (int i = 0; i < ITERATIONS; i++) {
            try {
                count = Integer.parseInt(Integer.toString(count)) + 1;
            } catch (NumberFormatException ex) {
                return null;
            }
        }
        return count;
    }
    public static Integer tryAroundLoop() {
        int count = 0;
        try {
            for (int i = 0; i < ITERATIONS; i++) {
                count = Integer.parseInt(Integer.toString(count)) + 1;
            }
            return count;
        } catch (NumberFormatException ex) {
            return null;
        }
    }
}

我使用 javap 检查生成的字节码以确保没有内联任何内容。

结果表明,假设 JIT 优化不重要, Jeffrey 是正确的在 Java 6、Sun 客户端 VM 上绝对没有性能差异(我没有访问其他版本)。在整个测试中,总时间差大约为几毫秒。

因此,唯一要考虑的是什么看起来最干净。我发现第二种方式很难看,所以我会坚持使用第一种方式或 Ray Hayes 的方式

原文由 Michael Myers 发布,翻译遵循 CC BY-SA 3.0 许可协议

表现:

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

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

该表被描述为大约一半。

原文由 Jeffrey L Whitledge 发布,翻译遵循 CC BY-SA 2.5 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题