之间存在效率差异: -
public boolean canDivisionBeDone(int iA, int iB){
try{
float a = iA/iB;
}catch(Exception e){
return false;
}
return true;
}
和
public boolean canDivisionBeDone(int iA, int iB){
if(iB == 0){
return false;
}else{
float a = iA/iB;
}
return true;
}
如果是,为什么?
答案 0 :(得分:1)
使用try
本身没有任何费用,但如果使用块创建了太多异常,则应尝试检查您的代码。
在Java中创建异常是一个非常慢的操作。期望抛出异常会花费你大约1-5微秒。几乎所有这些时间都花在填充异常线程堆栈上。堆栈跟踪越深,填充它的时间就越长。
有关详细信息,请参阅here
答案 1 :(得分:1)
从编码的角度来看,我肯定更喜欢条件(a == 0 ? 0 : (a/b)
),而不是异常处理。这实际上不是特殊情况,因此此处不应将异常用于控制流程。
关于效率,我写了一个微基准来测试这个:
@State(Scope.Thread)
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
public class MyBenchmark {
private int a = 10;
private int b = (int) Math.floor(Math.random());
@Benchmark
public float conditional() {
if (b == 0) {
return 0;
} else {
return a / b;
}
}
@Benchmark
public float exceptional() {
try {
return a / b;
} catch (ArithmeticException aex) {
return 0;
}
}
}
结果:
Benchmark Mode Cnt Score Error Units
MyBenchmark.conditional avgt 200 7.346 ± 0.326 ns/op
MyBenchmark.exceptional avgt 200 8.166 ± 0.448 ns/op
因为我对JMH很新,I am not sure my benchmark is correct。但是从表面上看结果,“特殊”方法有点(~10%)慢。说实话,我期待更大的差异。
答案 2 :(得分:0)
您想要传播回调用方的异常情况的例外情况。在正常操作期间不要依赖例外。
我只想把你的代码写成:
public boolean canDivisionBeDone(int iA, int iB) {
return iB != 0;
}
但回答你的问题:try-catch-finally
是使用离线异常表在Java中实现的,因此,当没有异常被抛出时,是zero-overhead
以下是两个函数的字节码的样子:
public boolean canDivisionBeDoneTryCatch(int, int);
Code:
0: iload_1
1: iload_2
2: idiv
3: i2f
4: fstore_3
5: goto 11
8: astore_3
9: iconst_0
10: ireturn
11: iconst_1
12: ireturn
Exception table:
from to target type
0 5 8 Class java/lang/Exception
public boolean canDivisionBeDoneIf(int, int);
Code:
0: iload_2
1: ifne 6
4: iconst_0
5: ireturn
6: iload_1
7: iload_2
8: idiv
9: i2f
10: fstore_3
11: iconst_1
12: ireturn
正如你所看到的那样,快乐的道路几乎完全相同。
但是,抛出异常是很昂贵的。
所以是的,我希望异常版本会稍慢,具体取决于iB == 0
情况的比例。
如有疑问,请以此为基准。