返回后使用try-finally执行语句

时间:2018-07-02 15:31:44

标签: java performance try-finally

考虑以下代码:

Foo result = array[index];
index = (index + 1) % array.length;
return result;

为了执行某些最终操作,需要一个额外的变量。将其写为:

try {
    return array[index];
} finally {
    index = (index + 1) % array.length;
}

还是会影响性能?通常,它被认为是一种好/不好的做法,如果是,为什么?

(在该示例中,假设indexarray的有效索引,并且代码不会抛出ArrayIndexOutOfBoundsException

编辑:问题不是关于使用try-finally的问题,而是关于我选择执行此操作所获得的任何性能损失。没有它,将创建一个变量。有了它,返回的值可能会以更有效的方式存储在其他位置。

2 个答案:

答案 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;