使用 try-finally 执行 return 之后的语句
Using try-finally to execute statements after return
考虑以下代码:
Foo result = array[index];
index = (index + 1) % array.length;
return result;
为了执行一些最终操作,需要一个额外的变量。写成这样有意义吗:
try {
return array[index];
} finally {
index = (index + 1) % array.length;
}
或者对性能有影响吗?通常,它被认为是一种 good/bad 做法,如果是,为什么?
(在示例中假定 index
是 array
的有效索引并且代码不会抛出 ArrayIndexOutOfBoundsException
)
编辑:问题不在于使用 try-finally
的必要性,而是关于我选择这样做所获得的任何性能增益或损失。没有它,就会创建一个变量。有了它,返回值存储在其他地方,也许以更有效的方式。
没有 finally
你确实声明了一个额外的 Foo
变量。
但它真的很贵吗?不像在这两种情况下 Foo
对象都存在于内存中。您刚刚添加了一个引用以访问它。
在方法范围内引用对象真的很便宜。
你永远不应该为此担心。
此外,您不必使用 finally
语句来提高执行代码的性能。
代码的读者永远猜不到这样的事情。
finally
用于:
The finally block always executes when the try block exits. This
ensures that the finally block is executed even if an unexpected
exception occurs.
和
putting cleanup code in a finally block is always a good practice,
even when no exceptions are anticipated.
没有 finally
语句的第一个代码更加清晰,并且没有任何阅读间接性。
所以我建议坚持:
Foo result = array[index];
index = (index + 1) % array.length;
return result;
如评论所述,主要开销是使用 %
而不是条件或掩码
您可以运行使用 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
可能会稍微慢一些,但与替代方案相比,我不会担心它。
考虑以下代码:
Foo result = array[index];
index = (index + 1) % array.length;
return result;
为了执行一些最终操作,需要一个额外的变量。写成这样有意义吗:
try {
return array[index];
} finally {
index = (index + 1) % array.length;
}
或者对性能有影响吗?通常,它被认为是一种 good/bad 做法,如果是,为什么?
(在示例中假定 index
是 array
的有效索引并且代码不会抛出 ArrayIndexOutOfBoundsException
)
编辑:问题不在于使用 try-finally
的必要性,而是关于我选择这样做所获得的任何性能增益或损失。没有它,就会创建一个变量。有了它,返回值存储在其他地方,也许以更有效的方式。
没有 finally
你确实声明了一个额外的 Foo
变量。
但它真的很贵吗?不像在这两种情况下 Foo
对象都存在于内存中。您刚刚添加了一个引用以访问它。
在方法范围内引用对象真的很便宜。
你永远不应该为此担心。
此外,您不必使用 finally
语句来提高执行代码的性能。
代码的读者永远猜不到这样的事情。
finally
用于:
The finally block always executes when the try block exits. This ensures that the finally block is executed even if an unexpected exception occurs.
和
putting cleanup code in a finally block is always a good practice, even when no exceptions are anticipated.
没有 finally
语句的第一个代码更加清晰,并且没有任何阅读间接性。
所以我建议坚持:
Foo result = array[index];
index = (index + 1) % array.length;
return result;
如评论所述,主要开销是使用 %
而不是条件或掩码
您可以运行使用 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
可能会稍微慢一些,但与替代方案相比,我不会担心它。