Java在for循环中使用getter还是创建局部变量?

sto*_*r96 11 java getter performance loops for-loop

我有一个运行4096次的for循环,它应该尽可能快.性能在这里非常重要.目前我在循环中使用getter方法,它只返回在循环进行时不会改变的字段中的值或对象.

例:

for (;;) {
    doSomething(example.getValue());
}
Run Code Online (Sandbox Code Playgroud)

使用getter是否有任何开销?使用以下方式更快吗?

例:

Object object = example.getValue();
for (;;) {
    doSomething(object);
}
Run Code Online (Sandbox Code Playgroud)

如果是,那么访问公共领域是否也是如此example.value

编辑:我不在System.out.println()循环内部使用.

编辑:某些字段不是final.没有字段,volatile也没有方法(getter)synchronized.

err*_*ist 7

正如Rogério所回答的那样,在循环(Object object = example.getValue();)之外获取对象引用可能比在循环内调用getter更快(或者至少永远不会更慢)因为

  • 在"最糟糕"的情况下,example.getValue()尽管getter方法应该是"微不足道的",但实际上可能会在后台执行一些非常耗费计算的东西.通过分配一次引用并重新使用它,您只需执行一次这种昂贵的计算.
  • 在"最好"的情况下,在JIT编译器内联代码之后,example.getValue()做一些微不足道的事情return value;,因此在循环中分配它并不比循环外部更昂贵.

但是,更重要的是两者之间的语义差异及其在多线程环境中可能产生的影响:如果对象的状态以example导致example.getValue()返回对不同对象的引用的方式发生变化,则有可能在每次迭代中,该方法doSomething(Object object)实际上将Object通过直接调用在不同的实例上操作doSomething(example.getValue());.另一方面,通过在循环外调用getter并设置对返回的instance(Object object = example.getValue();)的引用,doSomething(object);将对object n次迭代进行n次操作.

这种语义差异可能导致多线程环境中的行为与单线程环境中的行为完全不同.此外,这不一定是实际的"内存中"多线程问题:如果example.getValue()依赖于例如数据库/ HDD /网络资源,则在执行循环期间该数据可能会发生变化,从而可能使另一个对象成为可能.即使Java应用程序本身是单线程的,也会返回.因此,最好考虑使用循环实际完成的操作,然后选择最能反映预期行为的选项.


Boh*_*ian 5

这取决于吸气剂.

如果它是一个简单的吸气剂,JIT会将其内联到直接现场接入,因此不存在可衡量的差异.从样式的角度来看,使用getter - 它的代码更少.

如果getter正在访问一个volatile字段,则会有一个额外的内存访问命中,因为该值无法保存在寄存器中,但是命中非常小.

如果是getter synchronized,那么使用局部变量将会明显加快,因为不需要每次调用都可以获取和释放锁,但是循环代码将在调用getter时使用该字段的潜在过时值.