哪一个更好/更有效:在Java中检查错误值或捕获异常
在Java中,哪个更有效:检查错误值以防止异常,还是让异常发生并捕获它们 下面是两段示例代码来说明这种差异:哪一个更好/更有效:在Java中检查错误值或捕获异常,java,performance,exception,optimization,error-handling,Java,Performance,Exception,Optimization,Error Handling,在Java中,哪个更有效:检查错误值以防止异常,还是让异常发生并捕获它们 下面是两段示例代码来说明这种差异: void doSomething(type value1) { ResultType result = genericError; if (value1 == badvalue || value1 == badvalue2 || ...) { result = specificError; } else { DoSom
void doSomething(type value1) {
ResultType result = genericError;
if (value1 == badvalue || value1 == badvalue2 || ...) {
result = specificError;
} else {
DoSomeActionThatFailsIfValue1IsBad(value1);
// ...
result = success;
}
callback(result);
}
对
void doSomething(type value1) {
ResultType result = genericError;
try {
DoSomeActionThatFailsIfValue1IsBad(value1);
// ...
result = success;
} catch (ExceptionType e) {
result = specificError;
} finally {
callback(result);
}
}
一方面,你总是在做比较。另一方面,我真的不知道系统的内部如何生成异常,抛出异常,然后触发catch子句。它听起来效率较低,但如果在无错误的情况下不增加开销,那么平均而言,它的效率会更高。是哪一个?它是否添加了类似的检查?是否在隐式代码中添加了异常处理的检查,即使有额外的显式检查层?也许它总是取决于异常的类型?我没有考虑什么
让我们假设所有的“坏值”都是已知的——这是一个明显的问题。如果您不知道所有的错误值,或者列表太长且不规则,那么无论如何,异常处理可能是唯一的方法
那么,每种方法的优缺点是什么,为什么
要考虑的附带问题:
- 如果值在大多数情况下为“坏”(将引发异常),您的答案会如何变化李>
- 这在多大程度上取决于正在使用的虚拟机的具体情况
- 如果对language-X提出同样的问题,答案会不同吗?(更一般地说,这是在询问是否可以假设检查值总是比依赖异常处理更有效,因为这会增加当前编译器/解释器的开销。)
- (新)抛出异常的行为是缓慢的。即使没有抛出异常,输入try块也会有开销吗
因此:
- 这与中的代码示例相似,但说明它们仅在概念上相似,而不是在实际编译中
- 前提类似于,但在我的例子中,任务的请求者(例如“某物”)不是方法的调用方(例如“doSomething”)(因此没有返回)
- 非常相似,但我没有找到我问题的答案
- 与太多其他问题类似,除了: 我不是在问理论上的最佳实践。我想了解更多关于运行时性能和效率的信息(这意味着,对于特定情况,会有非意见的答案),特别是在资源有限的平台上。例如,如果唯一的坏值只是一个空对象,那么检查它是否更好/更有效,或者只是尝试使用它并捕获异常
类似地,您关于这个答案可能会随着语言/环境的变化而变化的问题与此相关:在不同的环境中,异常的代价是不同的。例如,Net 1.1和2.0在第一次抛出异常时速度非常慢。我个人的观点是,异常表明某些东西被破坏了-这很可能是一个使用非法参数调用的API,或者被零除或找不到文件等。这意味着可以通过检查值来抛出异常 对于代码的读者来说——同样是我个人的观点——如果你能确定它不会被各种奇怪的抛出(如果作为程序流的一部分使用,这本质上是伪装的gotos)所搁置,那么遵循流程就容易多了。你只需要想的更少 我认为这是一件好事。“智能”代码很难让人理解
另一方面,JVM要聪明得多,为提高效率而编码通常是没有回报的。纯粹从效率的角度来看,给出您的代码示例,我认为这取决于您希望看到坏值的频率。如果坏值不是很少见,那么比较会更快,因为异常是昂贵的。但是,如果坏值非常罕见,则使用异常可能会更快
不过,底线是,如果您正在寻找性能,请分析您的代码。这段代码甚至可能不值得关注。如果是的话,那么两种方法都试一下,看看哪个更快。同样,这取决于您希望看到错误值的频率。通常,人们会认为try-catch更昂贵,因为它在代码中看起来更重,但这完全取决于JIT。我的猜测是,如果没有一个真实的案例和一些性能度量,就不可能判断。比较可能更昂贵,尤其是当您有许多值时,例如,或者因为您必须调用
equals()
,因为==
在许多情况下都不起作用
至于您应该选择哪一个(如“代码样式”),我的回答是:确保用户在失败时收到有用的错误消息。其他任何东西都是品味的问题,我不能给你规则。我能找到的关于抛出异常的成本的信息非常少。很明显,一定有一些,您正在创建一个对象,可能正在获取堆栈跟踪信息 在您谈论的具体示例中:
if (value1 == badvalue || value1 == badvalue2 || ...) {
result = specificError;
} else {
DoSomeActionThatFailsIfValue1IsBad(value1);
// ...
result = success;
}
对于我来说,这里的问题是,如果(可能不完全)在调用方中复制应该由您调用的方法拥有的逻辑,您将面临危险
因此,我不会进行这些检查。您的代码不是在执行实验,而是在执行
public int IsAuthenticated(String username, String password)
{
if(!Validated(username,password)
{
// just an error
// log it
return -2;
}
// contacting the Database here
if cannot connect to db
{
// woww this is HUUGE
throw new DBException('cannot connect'); // or something like that
}
// validate against db here
if validated, return 0;
// etc etc
}
public void setAge(int age)
{
if(age < 0)
{
throw new IllegalArgumentException("Array can't be negative");
}
this.age = age;
}
public void readFile(String filename) throws IOException
{
File myfile = new File(filename);
FileInputStream fis = new FileInputStream(myfile);
//do stuff
fis.read();
//do more stuff
}