考虑以下代码:
Foo result = array[index];
index = (index + 1) % array.length;
return result;
为了执行某些最终操作,需要一个额外的变量。将其写为:
try {
return array[index];
} finally {
index = (index + 1) % array.length;
}
还是会影响性能?通常,它被认为是一种好/不好的做法,如果是,为什么?
(在该示例中,假设index
是array
的有效索引,并且代码不会抛出ArrayIndexOutOfBoundsException
)
编辑:问题不是关于使用try-finally
的问题,而是关于我选择执行此操作所获得的任何性能损失。没有它,将创建一个变量。有了它,返回的值可能会以更有效的方式存储在其他位置。
答案 0 :(得分:5)
如前所述,主要开销是使用%
而不是条件或掩码
您可以使用JMH运行基准测试
static class Foo {
}
Foo[] array = new Foo[8];
int index = 0;
@Benchmark
public Foo simple() {
Foo result = array[index];
index = (index + 1) % array.length;
return result;
}
@Benchmark
public Foo withFinally() {
try {
return array[index];
} finally {
index = (index + 1) % array.length;
}
}
@Benchmark
public Foo withCondition() {
int i = index++;
if (index == array.length) index = 0;
return array[i];
}
@Benchmark
public Foo withMask() {
int i = index++;
return array[i & (array.length-1)];
}
我机器上的结果...您的里程会变化
Benchmark Mode Cnt Score Error Units
ModMain.simple thrpt 25 132.473 ± 1.764 ops/us
ModMain.withCondition thrpt 25 363.077 ± 4.752 ops/us
ModMain.withFinally thrpt 25 130.179 ± 1.585 ops/us
ModMain.withMask thrpt 25 397.310 ± 3.506 ops/us
越高越好。
简而言之,使用finally
可能会稍微慢一些,但是与其他方法相比,我不会担心。
答案 1 :(得分:2)
如果没有finally
,则实际上声明了一个额外的Foo
变量。
但这真的很贵吗?并非在两种情况下Foo
对象都存在于内存中。您刚刚添加了对其进行访问的参考。
在方法范围内对对象的引用确实很便宜。
您永远不必为此担心。
此外,您不必使用finally
语句来提高已执行代码的性能。
代码的读者永远不会猜到这样的事情。
finally
用于:
try块退出时,finally块始终执行。这个 确保即使遇到意外情况,finally块也将执行 发生异常。
和
将清理代码放在finally块中始终是一种好习惯, 即使没有例外。
第一个没有finally
语句的代码更加清晰,没有任何间接的读取方式。
所以我建议坚持:
Foo result = array[index];
index = (index + 1) % array.length;
return result;