哪个更好/更有效:检查错误值或捕获Java中的异常

lil*_*die 14 java error-handling optimization performance exception

哪个在Java中更有效:检查错误值以防止异常或让异常发生并捕获它们?

以下是两个示例代码块,用于说明这种差异:

void doSomething(type value1) {
    ResultType result = genericError;

     if (value1 == badvalue || value1 == badvalue2 || ...) {
          result = specificError;
     } else {
          DoSomeActionThatFailsIfValue1IsBad(value1);
          // ...
          result = success;
     }
     callback(result);
}
Run Code Online (Sandbox Code Playgroud)

void doSomething(type value1) {
     ResultType result = genericError;
     try {
          DoSomeActionThatFailsIfValue1IsBad(value1);
          // ...
          result = success;
     } catch (ExceptionType e) {
          result = specificError;
     } finally {
          callback(result);
     }
}
Run Code Online (Sandbox Code Playgroud)

一方面,你总是在进行比较.另一方面,老实说,我不知道系统的内部做什么来生成异常,抛出它,然后触发catch子句.它有效率较低的声音,但如果它不会在非错误情况下增加开销,那么它的平均效率会更高.这是什么?它是否会添加类似的检查?是否在为异常处理添加的隐式代码中检查,即使有额外的显式检查层?也许它总是取决于异常的类型?我不考虑什么?

让我们假设所有"坏值"都是已知的 - 这是一个明显的问题.如果您不知道所有错误的值 - 或者列表太长且不规则 - 那么异常处理可能是唯一的方法.

那么,每种方法的优缺点是什么?为什么?

需要考虑的问题:

  • 如果值在大多数情况下是"坏"(会抛出异常),你的答案会如何变化?
  • 这有多少取决于正在使用的VM的细节?
  • 如果要求语言-X提出同样的问题,答案会有所不同吗?(更一般地说,问题是否可以假设检查值总是比依赖异常处理更有效,因为它增加了当前编译器/解释器的开销.)
  • (新)抛出异常的行为很慢.输入try块是否有开销,即使没有抛出异常?

与SO的相似之处:

  • 这类似于本答案中的代码示例,但声明它们仅在概念上相似,而不是编译现实.
  • 前提是类似于这个问题,但在我的情况下,任务的请求者(例如"Something")不是方法的调用者(例如"doSomething")(因此没有返回).
  • 这一个是非常相似的,但我没有找到一个回答我的问题.

  • 类似于要列出的其他许多问题,除了:

    我不是在问理论最佳实践.我要求更多关于运行时性能和效率(这应该意味着,对于特定情况,有非意见答案),特别是在资源有限的平台上.例如,如果唯一的错误值只是一个空对象,那么检查它或者只是尝试使用它并捕获异常会更好/更有效吗?

T.J*_*der 9

" 如果价值在大多数情况下是"坏"(会抛出异常),你的答案如何改变? "我认为那是关键.与比较相比,例外是昂贵的,因此您确实希望在例外条件下使用例外.

同样,关于这个答案如何根据语言/环境而变化的问题与此相关:异常的费用在不同的环境中是不同的.例如,在第一次抛出异常时,.Net 1.1和2.0 非常慢.


Ada*_*ume 6

纯粹从效率的角度来看,并且考虑到您的代码示例,我认为这取决于您期望看到错误值的频率.如果不好的值不太常见,那么进行比较会更快,因为异常是昂贵的.但是,如果错误的值非常罕见,则使用异常可能会更快.

但最重要的是,如果您正在寻找性能,请分析您的代码.这段代码甚至可能不是一个问题.如果是,那么尝试两种方式,看看哪个更快.同样,这取决于您期望看到不良价值的频率.


Jay*_*Jay 2

在我看来,如果只是为了有一个安全运行的系统,你应该在任何可能引发异常的地方使用 try/catch 块。如果您首先检查可能的数据错误,则可以更好地控制错误响应。所以我建议两者都做。