如果在代码中没有修改它,我应该声明一个java字段'final'吗?

时间:2011-08-15 15:48:07

标签: java performance final

我的问题主要是关于表现。编译器更清楚地知道,例如,在对象实例化之后,某些变量未被修改。那么,为什么还要打扰决赛?

我认为可能会有许多结构/逻辑原因,但从性能的角度来讲?这有关系吗?

谢谢,

7 个答案:

答案 0 :(得分:20)

现代 JVM中,最终的不应影响性能。对于私有字段尤其如此,但即使对于非私有字段,JIT也可以优化非最终字段,因为它们是最终的,然后deoptimize如果它加载了一些实际上会修改字段的代码。

也就是说,使用final的主要原因不是性能,而是使代码更易于维护。通过最终制作字段,您可以减少代码中“移动部件”读取器的数量,从而更容易推理代码。

答案 1 :(得分:8)

我怀疑从性能的角度来看这很重要,但是如果您(但更有可能是其他新开发人员)稍后尝试在代码中修改该字段,它仍然可能是一个好主意。将其标记为final将阻止您进行编译。

答案 2 :(得分:7)

对字段使用final也会影响线程安全性Java Memory Model表示final字段的值对于可以在该对象的构造函数完成后立即访问该对象的所有线程可见。该保证类似于volatile字段,其中任何线程始终看到当前值。普通领域没有这样的保证。

而且,正如其他人所指出的那样,JIT可以对final字段执行积极的优化,这对于普通字段来说并不容易,其中任何新加载的类都可以对字段进行写访问。

答案 3 :(得分:5)

final在编译时用于接受或拒绝您的源代码有效。它不应该有任何运行时的影响。

答案 4 :(得分:5)

如果该字段不是private,那么JVM将始终必须准备好在某个时间加载尚未遇到的类并开始修改它。因此,对于那些字段,可以明确声明它们final将允许在JIT中进行更强的优化。如果JIT一次只查看一个方法,那么私有字段甚至可能是这样。

另一方面,局部变量上的final不能在字节码编译中存活,因此应该没有性能影响。

答案 5 :(得分:3)

对于局部变量,最终修饰符不保留在字节码中,因此不存在性能差异。对于现场成员,性能影响更复杂。它可能会给jit提示该字段未被修改并允许它将值缓存在寄存器中。另一方面,final确实给出了关于字段值对其他线程的可见性的一些保证,这实际上可能会减慢对象构建速度。

性能明智我认为这是一种微观优化,其效果难以衡量。

我仍然建议尽可能使用final来澄清你对同事和未来自己的意图。

答案 6 :(得分:1)

使用final并不是对编译器或JIT的暗示。这是对自己或维护代码的其他开发人员的暗示。它清楚地表明类代码的其余部分假定该字段永远不会改变,这可能是一个特别重要的事情(例如,出于正确性和/或线程安全性原因)。它还确保子类不会更改其值(如果字段为protected)。

如果参与其值的所有字段都是最终的,则可以缓存对象的hashCode