PNS*_*PNS 55 java if-statement exception-handling try-catch overhead
Java中是否存在使用try/catch块的开销,而不是if块(假设所附的代码没有请求)?
例如,对字符串采用以下两种简单的"安全修剪"方法:
public String tryTrim(String raw) {
try {
return raw.trim();
} catch (Exception e) {
}
return null;
}
public String ifTrim(String raw) {
if (raw == null) {
return null;
}
return raw.trim();
}
Run Code Online (Sandbox Code Playgroud)
如果raw输入很少null,两种方法之间是否有任何性能差异?
此外,使用该方法简化代码布局是一种很好的编程模式tryTrim(),特别是当通过将代码封装在一个try/catch块中可以避免许多if块检查稀有错误条件时?
例如,一个常见的情况是使用一个方法N parameters,M <= N在其开始附近使用它们,如果任何这样的参数是"无效的"(例如,空或空字符串),则快速且确定地失败,而不影响其余的码.
在这种情况下,不必编写k * M if块(其中k每个参数的平均检查次数,例如k = 2对于null或空字符串),try/catch块将显着缩短代码并且可以使用1-2行注释明确地注意到"非常规"逻辑.
这样的模式也会加速该方法,特别是如果错误条件很少发生,并且它会这样做而不会影响程序安全性(假设错误条件是"正常"的,例如在字符串处理方法中为null或空值)是可以接受的,虽然很少存在).
Tro*_*ott 63
我知道你在询问性能开销,但你真的不应该使用try/ catch和if互换.
try/ catch适用于您无法控制但不在正常程序流程中的错误.例如,尝试写入文件并且文件系统已满?这种情况通常应该用try/ 来处理catch.
if语句应该是正常流程和普通错误检查.那么,例如,用户无法填充所需的输入字段?使用if该,不try/ catch.
在我看来,您的示例代码强烈建议正确的方法有一个if声明而不是try/ catch.
要回答你的问题,我会猜测,有一个一般更多的开销try/ catch比if.要确定,请获取Java分析器并找出您关心的特定代码.答案可能会因情况而异.
Ste*_*n C 33
这个问题几乎已经"回归死亡",但我认为还有一些问题可以有用:
使用try / catch非异常控制流是不好的风格(在Java中).(关于"非例外"的含义经常存在争议......但这是一个不同的主题.)
部分原因是坏的风格是,try / catch是数量级比常规的控制流语句更贵1.实际的差异取决于程序和平台,但我预计它会高出1000倍或更多倍.除此之外,创建异常对象捕获堆栈跟踪,查找和复制有关堆栈上每个帧的信息.堆栈越深,需要复制的越多.
它风格不好的另一个原因是代码难以阅读.
1 - 在某些情况下,Java 7的最新版本中的JIT可以优化异常处理,从而大幅减少开销.但是,默认情况下不启用这些优化.
您编写示例的方式也存在问题:
捕获Exception是非常糟糕的做法,因为您有可能偶然捕获其他未经检查的异常.例如,如果你这样做,那么你raw.substring(1)也会抓住潜在StringIndexOutOfBoundsException的......并隐藏错误.
你的例子试图做的(可能)是处理null字符串的不良做法的结果.作为一般原则,您应该尽量减少null字符串的使用,并尝试限制它们(有意)的传播.在可能的情况下,使用空字符串而不是null表示"无价值".当你遇到需要传递或返回null字符串的情况时,请在方法javadocs中清楚地记录它.如果你的方法被调用,null他们不应该...它是一个错误.让它抛出异常.不要试图通过(在这个例子中)返回来弥补错误null.
跟进
我的问题更为笼统,不仅仅是空值.
......我的答案中的大多数要点都不是关于空值!
但请记住,在许多情况下,您希望允许偶尔出现空值或任何其他可能产生异常的值,并忽略它们.例如,当从某处读取键/对值并将它们传递给上面的tryTrim()之类的方法时就是这种情况.
是的,有些情况下会出现null价值,您需要处理它们.
但我认为tryTrim()正在做的事情(通常)是错误的处理方式null.比较这三位代码:
// Version 1
String param = httpRequest.getParameter("foo");
String trimmed = tryTrim(param);
if (trimmed == null) {
// deal with case of 'foo' parameter absent
} else {
// deal with case of 'foo' parameter present
}
// Version 2
String param = httpRequest.getParameter("foo");
if (param == null) {
// deal with case of 'foo' parameter absent
} else {
String trimmed = param.trim();
// deal with case of 'foo' parameter present
}
// Version 3
String param = httpRequest.getParameter("foo");
if (param == null) {
// treat missing and empty parameters the same
param = "";
}
String trimmed = param.trim();
Run Code Online (Sandbox Code Playgroud)
最终你必须以null不同于常规字符串的方式处理它,并且通常最好尽快做到这一点.进一步的null,允许从其原点传播,越有可能是,程序员会忘记一个null值是一个可能性,并编写假定非空值bug的代码.并且忘记了HTTP请求参数可能丢失(即param == null)是发生这种情况的经典案例.
我不是说这tryTrim()本身就是坏事.但是程序员认为需要这样的写方法的事实可能表明不太理想的空值处理.
Ant*_*ram 10
使用第二个版本.当其他替代品可用时,切勿使用控制流的例外情况,因为这不是它们的用途.例外情况适用于特殊情况.
关于这个话题,不要抓住Exception这里,特别是不要吞下它.在你的情况下,你会期望一个NullPointerException.如果你要抓住一些东西,那就是你会抓到的东西(但回到第一段,不要这样做).当你抓住(并吞下!)Exception,你说"不管出了什么问题,我都能处理它.我不在乎它是什么." 您的程序可能处于不可撤销的状态!只捕捉你准备处理的内容,让其他所有内容传播到一个可以处理它的层,即使该层是顶层,它只是记录异常,然后点击弹出开关.
否则异常抛出和捕获的速度很快(尽管 anif可能仍然更快),但慢的是创建异常的堆栈跟踪,因为它需要遍历所有当前堆栈。(一般来说,在控制流中使用异常是不好的,但是当确实需要并且异常必须快速时,可以通过覆盖Throwable.fillInStackTrace()方法跳过构建堆栈跟踪,或者保存一个异常实例并重复抛出它而不是总是创建一个新的异常实例。)
| 归档时间: |
|
| 查看次数: |
35493 次 |
| 最近记录: |