11

假设savethrowsi仅用于save. 以下代码片段是否相同?请考虑语义、性能和其他方面。

void bob(){
  int i = calculate();
  try {
    save(i);
  } catch(Exception e){
    report(e)
  }
}

对比

void bob(){
  try {
    int i = calculate();
    save(i);
  } catch(Exception e){
    report(e)
  }
}

一般来说,我想知道,应该将一个函数的所有语句放在一个try-catch块中还是只放在一个块中。

4

4 回答 4

12

语义方面,如果您已经决定了要将 try-catch 构造放入哪种方法(并且您对自己做出正确的决定感到满意),那么答案相当简单:

  • 您应该在try中包含一系列语句,这样,如果其中一个语句失败,则应该放弃该序列的其余部分。没有更多也没有更少的陈述。

如果您正确地遵循上述建议,诸如所需的程序流程和最有效的局部变量作用域之类的问题将非常容易且明显地得到解决(在大多数情况下)。您会注意到这并不排除嵌套try块的可能性。

在性能方面,异常处理的开销在于实际抛出和捕获可抛出对象。换句话说,只有真正发生异常时才会真正产生开销。代码中仅存在 try-catch 结构不会引入任何可测量的开销(可能根本没有)。此外,语句的数量(在给定的 try-catch 结构中)与其性能完全无关。

编辑:我在 JVM 规范中找不到要链接的任何详细信息,但是用户有很多帖子检查和解释生成的字节码,比如这个这个(以及许多其他的 - 谷歌搜索会产生一些有趣的结果)。对我来说,看起来 Java 编译器试图尽可能少地发出(当然,除了你放入的实际代码trycatch子句和一些不可避免的程序流指令来跳过所述子句或弹出异常对象(如果有)。它让 VM 负责找出异常在哪里被捕获。这很可能会将更多的负担转移到实际发生异常的场景中,但正如我们所知,异常是针对异常情况的,而不是控制流。

我承认我不知道 C++ 异常通常是如何实现的,但是考虑到 C++ 程序通常不会在 VM 的帮助下运行,它们与 Java 的完全不同是非常合理的。

于 2013-06-20T19:24:09.450 回答
5

他们不一样。不同之处在于变量的范围i。在第二种情况下,您不能在块i外使用。try-catch

一般来说,我想知道,一个函数的所有语句应该放在一个 try-catch 块中还是只放在一个抛出中。

更好的方法是将易受异常抛出的代码封装在try-catch块内。这样,您可以处理与特定代码块相关的特定异常。因此,第一种方法是要走的路。

于 2013-06-20T19:21:02.003 回答
2

在这种情况下:

void bob(){
  try {
    int i = calculate();
    save(i);
  } catch(Exception e){
    report(e)
  }
}

所有异常(除了错误)都会被捕获,因为异常是所有类型的超类Exception(除了错误)。因此,不仅会处理已检查的异常,还会处理未检查RuntimeException的异常。如果这是您的目标,那么我建议您遵循这种方式。另一方面,我认为最小化try...catch块的范围是一个很好的做法,因为在异常情况下定位有问题的代码行更容易。

于 2013-06-20T19:26:30.433 回答
1

Rohit 指出(正确地)变量的范围在i这里有所不同。

额外的区别是如果calculate()抛出一个未经检查的异常;它会被catch方块抓住。是否应该将调用放在calculate()块内try取决于您是要从此处calculate()catch块中处理未经检查的异常,还是允许它向外抛出。在我看来,因为它是 Unchecked 并且因此完全出乎意料,所以我不会calculate()try块中调用 to。

关于性能,我认为应该没有区别,因为性能影响是在遇到try块时,而在这两种情况下你只有一个块。如果您try-catch在每行周围有单独的块,如下所示,那么性能可能会降低,但可能不会以您从未注意到的任何方式:

// degraded performance example
void bob(){

    int i;

    try {
        i = calculate();
    } catch(Exception e){
        report(e)
    }

    try {
        save(i);
    } catch(Exception e){
        report(e)
    }
}
于 2013-06-20T19:25:49.960 回答