Java编译器是否优化了数组索引查找? for(int i=0;i

Java编译器是否优化了数组索引查找? for(int i=0;i,java,compiler-construction,Java,Compiler Construction,在这样的代码中,设置像currentValue=array[i]这样的变量,然后引用该变量而不是array[i],是否真的有用?我觉得编译器应该足够聪明,可以做类似的事情,并使这些代码变得毫无意义。如果你阅读编译器生成的字节码,你会发现它没有进行这样的优化。这意味着在解释模式下,每次都将执行数组查找。如果带有循环的方法运行足够多次,JIT编译器将对其进行另一次检查,并可能对其进行优化 结论:如果希望得到可预测的结果,请将数组元素存储在局部变量中。更重要的是,这样代码的可读性也更高。如果您阅读编译

在这样的代码中,设置像
currentValue=array[i]
这样的变量,然后引用该变量而不是
array[i]
,是否真的有用?我觉得编译器应该足够聪明,可以做类似的事情,并使这些代码变得毫无意义。

如果你阅读编译器生成的字节码,你会发现它没有进行这样的优化。这意味着在解释模式下,每次都将执行数组查找。如果带有循环的方法运行足够多次,JIT编译器将对其进行另一次检查,并可能对其进行优化


结论:如果希望得到可预测的结果,请将数组元素存储在局部变量中。更重要的是,这样代码的可读性也更高。

如果您阅读编译器生成的字节码,您将看到它没有进行此类优化。这意味着在解释模式下,每次都将执行数组查找。如果带有循环的方法运行足够多次,JIT编译器将对其进行另一次检查,并可能对其进行优化


结论:如果希望得到可预测的结果,请将数组元素存储在局部变量中。更重要的是,这样代码的可读性也更高。

转换创建另一个引用副本的好处是什么?JIT需要该循环被另一个循环循环循环,从而进入优化。作为一般规则,相信编译器比你聪明,直到你有硬数字显示出来。争取可读性和清晰性。这样的微观优化不会有任何明显的效果,如果有的话。因此,如果你发现引入局部变量更清晰,那么就这样做。事实上,在许多这样的情况下,“规则”会阻止编译器(或JITC)对这些访问进行“公共化”。在很多情况下,使用temp比重复访问更清晰,因为更容易看到相同的值被多个地方使用。转换创建另一个引用副本的好处是什么?JIT需要该循环被另一个循环循环循环,然后进入优化。一般来说,相信编译器比你聪明,直到你有硬数字显示出来。争取可读性和清晰性。这样的微观优化不会有任何明显的效果,如果有的话。因此,如果你发现引入局部变量更清晰,那么就这样做。事实上,在许多这样的情况下,“规则”会阻止编译器(或JITC)对这些访问进行“公共化”。在很多情况下,使用temp比重复访问更清晰,因为更容易看到相同的值被多个位置使用。您是否测量过将其存储在私有变量中,即使是未优化的,也会更快?@JBNizet-值得注意的是,不仅消除了第二次数组访问,而且还要检查该访问的数组边界。在优化的JITC中,如果“规则”禁止JITC共享访问,那么第二个访问是第二个潜在的异常点,它“破坏”了其他优化。我同意这一点,它可能更快,但如果没有度量,我不会盲目地认为它更快。无论如何,与优化IO、DB请求等相比,这可能会产生微不足道的影响。我也同意,引入局部变量通常更容易修改。@jbniset,执行所有那些
iload
aload
操作码,无论它们有多小,但我同意现实生活中的性能可能很难预测。您是否测量过将其存储在私有变量(即使是未优化的)中的速度可以预测?@JBNizet-值得注意的是,不仅消除了第二次数组访问,而且还消除了该访问的数组边界检查。在优化的JITC中,如果“规则”禁止JITC共享访问,那么第二个访问是第二个潜在的异常点,它“破坏”了其他优化。我同意这一点,它可能更快,但如果没有度量,我不会盲目地认为它更快。无论如何,与优化IO、DB请求等相比,这可能会产生微不足道的影响。我也同意,引入局部变量通常更容易修改。@jbniset,执行所有那些
iload
aload
操作码,无论它们有多小,但我同意现实生活中的表现很难预测。
        for (int i = 0; i < array.length; ++i) {
            do something referencing array[i]
            do something referencing array[i]
            ....
        }