应该尽可能严格地限制java try块的范围吗? [英] Should java try blocks be scoped as tightly as possible?

查看:473
本文介绍了应该尽可能严格地限制java try块的范围吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我被告知使用Java try-catch机制有一些开销。因此,虽然有必要在try块中抛出被检查的异常来处理可能的异常,但是将try块的大小限制为只包含那些可能引发异常的操作是很好的做法。 p>

我不太确定这是一个明智的结论。



考虑下面的两个实现,处理一个指定的文本文件。



即使第一个引起了一些不必要的开销,我发现更容易遵循。不太清楚,只是从查看声明出来的例外情况,但是评论清楚地显示哪些陈述是负责的。



第二个是比首先。特别是,第一个不错的线阅读成语必须被调整以适应 readLine 调用到一个try块。



在定义中可能会抛出多个异常的函数中处理异常的最佳做法是什么?



这一个包含尝试中的所有处理代码块:

  void processFile(File f)
{
try
{
//构建FileReader可以抛出FileNotFoundException
BufferedReader in = new BufferedReader(new FileReader(f));

// readLine的调用可以抛出IOException
String line;
while((line = in.readLine())!= null)
{
process(line);
}
}
catch(FileNotFoundException ex)
{
handle(ex);
}
catch(IOException ex)
{
句柄(ex);
}
}

这一个只包含在try中抛出异常的方法块:

  void processFile(File f)
{
FileReader reader;
try
{
reader = new FileReader(f);
}
catch(FileNotFoundException ex)
{
handle(ex);
返回;
}

BufferedReader in = new BufferedReader(reader);

字符串;
while(true)
{
try
{
line = in.readLine();
}
catch(IOException ex)
{
句柄(ex);
break;
}

if(line == null)
{
break;
}

进程(行);
}
}


解决方案

这里的基本前提是 false: try 块的大小在性能上没有差别。性能受到在运行时实际引发异常的影响,这与 try 块的大小无关。



然而可能会导致更好的程序。



您可能会捕获异常以恢复并继续,或者您可能只需要将其报告给调用者(或一个人,通过一些UI)。



在第一种情况下,您可以恢复的故障通常是非常具体的,这导致较小的尝试块。



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



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






知道什么效果可能是有用的一个 try 块对已编译的代码。完全没有改变编译说明! (当然,相应的 catch 块,因为它像任何其他代码一样。)



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



重要的是要意识到这个表不被查阅(并且对运行性能没有影响),除非这是必要的。 (忽略加载课程时的一点开销。)


I've been told that there is some overhead in using the Java try-catch mechanism. So, while it is necessary to put methods that throw checked exception within a try block to handle the possible exception, it is good practice performance-wise to limit the size of the try block to contain only those operations that could throw exceptions.

I'm not so sure that this is a sensible conclusion.

Consider the two implementations below of a function that processes a specified text file.

Even if it is true that the first one incurs some unnecessary overhead, I find it much easier to follow. It is less clear where exactly the exceptions come from just from looking at statements, but the comments clearly show which statements are responsible.

The second one is much longer and complicated than the first. In particular, the nice line-reading idiom of the first has to be mangled to fit the readLine call into a try block.

What is the best practice for handling exceptions in a funcion where multiple exceptions could be thrown in its definition?

This one contains all the processing code within the 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);
  }
}

This one contains only the methods that throw exceptions within try blocks:

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);
  }
}

解决方案

The basic premise here is false: the size of a try block makes no difference in performance. Performance is affected by actually raising exceptions at runtime, and that's independent of the size of the try block.

However, keeping try blocks small can lead to better programs.

You might catch exceptions to recover and proceed, or you might catch them simply to report them to the caller (or to a human, via some UI).

In the first case, failures from which you can recover are often very specific, and this leads to smaller try blocks.

In the second case, where an exception is caught so that it can be wrapped by another exception and re-thrown, or displayed to the user, small try blocks mean that you know more precisely which operation failed, and the higher-level context in which that call was made. This allows you to create more specific error reports.

Of course, there are… exceptions (sorry!) to these guidelines. For example, in some cases very specific error reports could be a security problem.


It might be useful to know what effect a try block has on the compiled code. It doesn't change the compiled instructions at all! (Of course, the corresponding catch block does, since it's like any other code.)

A try block creates an entry in the exception table associated with the method. This table has a range of source instructions counters, an exception type, and a destination instruction. When an exception is raised, this table is examined to see if there is an entry with a matching type, and a range that includes the instruction that raised the exception. If it does, execution branches to the corresponding destination number.

The important thing to realize is that this table isn't consulted (and has no effect on running performance) unless it's needed. (Neglecting a little overhead in the loading of the class.)

这篇关于应该尽可能严格地限制java try块的范围吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆