gpt4 book ai didi

java - 访问 final 局部变量是否比 Java 中的类变量更快?

转载 作者:太空狗 更新时间:2023-10-29 23:01:06 31 4
gpt4 key购买 nike

我一直在研究一些 Java 原始集合(trovefastutilhppc),我注意到一种模式,即类变量有时被声明为 final 局部变量。例如:

public void forEach(IntIntProcedure p) {
final boolean[] used = this.used;
final int[] key = this.key;
final int[] value = this.value;
for (int i = 0; i < used.length; i++) {
if (used[i]) {
p.apply(key[i],value[i]);
}
}
}

我已经做了一些基准测试,看起来它在执行此操作时稍微更快,但为什么会这样?我试图了解如果注释掉该函数的前三行,Java 会有什么不同。

注意:这似乎类似于 this question ,但那是针对 C++ 的,并没有说明为什么将它们声明为 final

最佳答案

访问局部变量或参数是一个单步操作:取一个位于堆栈偏移 N 处的变量。如果您的函数有 2 个参数(简化):

  • N = 0 - 这个
  • N = 1 - 第一个参数
  • N = 2 - 第二个参数
  • N = 3 - 第一个局部变量
  • N = 4 - 第二个局部变量
  • ...

所以当你访问局部变量时,你有一个固定偏移量的内存访问(N 在编译时已知)。这是访问第一个方法参数 (int) 的字节码:

iload 1  //N = 1

然而,当您访问字段时,您实际上是在执行一个额外的步骤。首先,您读取“局部变量this 只是为了确定当前对象地址。然后您正在加载一个字段 (getfield),它与 ​​this 有一个固定的偏移量。所以你执行了两个内存操作而不是一个(或一个额外的)。字节码:

aload 0  //N = 0: this reference
getfield total I //int total

所以技术上访问局部变量和参数比对象字段更快。实际上,许多其他因素可能会影响性能(包括各种级别的 CPU 缓存和 JVM 优化)。

final 是另一回事。这基本上是对编译器/JIT 的一个提示,即此引用不会更改,因此它可以进行一些更重的优化。但这更难追踪,根据经验,尽可能使用 final

关于java - 访问 final 局部变量是否比 Java 中的类变量更快?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6602922/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com