代码之家  ›  专栏  ›  技术社区  ›  Iain Samuel McLean Elder

java try块的作用域应该尽可能紧密吗?

  •  40
  • Iain Samuel McLean Elder  · 技术社区  · 15 年前

    我听说在使用Java try-catch机制时会有一些开销。因此,虽然有必要将抛出选中异常的方法放在try块中来处理可能的异常,但将try块的大小限制为只包含那些可能抛出异常的操作是一种良好的做法。

    请考虑以下函数的两个实现:处理指定文本文件的函数。

    即使第一种方法确实会带来一些不必要的开销,我发现它更容易理解。仅仅从语句的角度来看,不太清楚例外情况究竟来自何处,但注释清楚地表明了哪些语句是负责的。

    第二个比第一个长得多,复杂得多。特别是,第一个好的行读习惯用法必须被破坏,以适应 readLine 呼叫try block。

    在函数定义中可以抛出多个异常的情况下,处理异常的最佳实践是什么?

    void processFile(File f)
    {
      try
      {
        // construction of FileReader can throw FileNotFoundException
        BufferedReader in = new BufferedReader(new FileReader(f));
    
        // call of readLine can throw IOException
        String line;
        while ((line = in.readLine()) != null)
        {
          process(line);
        }
      }
      catch (FileNotFoundException ex)
      {
        handle(ex);
      }
      catch (IOException ex)
      {
        handle(ex);
      }
    }
    

    此方法仅包含在try块中引发异常的方法:

    void processFile(File f)
    {
      FileReader reader;
      try
      {
        reader = new FileReader(f);
      }
      catch (FileNotFoundException ex)
      {
        handle(ex);
        return;
      }
    
      BufferedReader in = new BufferedReader(reader);
    
      String line;
      while (true)
      {
        try
        {
          line = in.readLine();
        }
        catch (IOException ex)
        {
          handle(ex);
          break;
        }
    
        if (line == null)
        {
          break;
        }
    
        process(line);
      }
    }
    
    7 回复  |  直到 15 年前
        1
  •  48
  •   erickson    15 年前

    错误: try 块在性能上没有区别。性能受到运行时实际引发异常的影响,这与异常的大小无关 尝试 阻止。

    然而,保持try块小可以得到更好的程序。

    在第一种情况下,可以从中恢复的故障通常非常具体,这会导致较小的故障 阻碍。

    在第二种情况下,捕获一个异常,以便它可以被另一个异常包装并重新抛出,或向用户显示 尝试 块意味着您可以更准确地知道哪个操作失败,以及发出调用的更高级别上下文。这允许您创建更具体的错误报告。

    当然,也有例外(对不起!)遵守这些准则。例如,在某些情况下,非常具体的错误报告可能是一个安全问题。


    了解一个 尝试 块对已编译的代码有影响。它根本不会改变编译后的指令(当然,相应的 catch

    A. 尝试 块在与方法关联的异常表中创建一个条目。此表包含一系列源指令计数器、异常类型和目标指令。引发异常时,将检查此表以查看是否存在具有匹配类型的条目,以及包含引发异常的指令的范围。如果是,则执行分支到相应的目标编号。

    要认识到的重要一点是,除非需要,否则不会参考此表(并且对运行性能没有影响)(忽略了课堂上的一些开销。)

        2
  •  12
  •   Jonathon Faust    15 年前

    我听说在使用Java try-catch机制时会有一些开销。

    不要吹嘘过早的优化号角,但重点应该放在易于阅读、组织等方面。语言结构很少像系统组织和算法选择那样影响性能。

    对我来说,第一个最容易阅读。

        3
  •  3
  •   CurtainDog    15 年前

        4
  •  2
  •   luis.espinal    15 年前

    这是最糟糕的过早优化。别这么做。

    “我们应该忘记小效率,比如说97%的时间:过早的优化是万恶之源”—Knuth。

        5
  •  1
  •   chris    15 年前

    只要你用一个“逻辑”块来限定它的范围,即一次打开、读取和关闭一个文件,我就用第一种方法。它的读取要简单得多,特别是在处理IO时,try-catch开销所使用的处理器周期将非常小(如果有的话)。

        6
  •  1
  •   Marcus Adams    15 年前

    但是,大多数人提到的性能问题与引发异常有关,而与try块本身无关。

        7
  •  0
  •   Matt McHenry    15 年前

    第二个方法将生成一个编译器错误 reader null ,但这只是意味着你可以得到一个NPE,这是没有好处的。