什么是可以作为运行时常量?

时间:2014-05-27 16:36:33

标签: java access-modifiers

必须是private + static + final才能作为编译时常量内联吗?

什么可以作为运行时常量?

怎么样:

private final ...
static final ...
final ...

4 个答案:

答案 0 :(得分:2)

访问修饰符对内联没有影响。

重要的是,值来自常量表达式(http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.28)以及它的合适类型(基元或字符串)。

虽然可以通过多种方式更改最终赋值(最简单的方法是使用新值重新编译包含的类),但如果支持上述限制,它们仍会被视为常量。因此即使 public 最终静态也可以(并经常 )内联编译时间。

答案 1 :(得分:2)

JLS 4.12.4指定“常量变量”是什么。基本上,要求是它必须是final,类型是基本类型或字符串,并且值必须是常量表达式(15.28)。

常量变量的值将由字节码编译器内联。

JLS规则不区分static或不区分不同的访问修饰符。


  

但是公共静态final可以通过反射来改变,那么它是编译时最终的吗?

是。实际上,对常量变量的反射性变化没有影响:

  

“即便如此,还有许多复杂情况。如果在字段声明中将最终字段初始化为常量表达式(第15.28节),则可能无法观察到对最终字段的更改,因为使用了final字段在编译时被替换为常量表达式的值。“ - JLS 17.5.3


  

什么可以作为运行时常量?

有趣的问题。我没有看到JLS中直接提到的那个问题。然而,显然可以反思这一点(考虑到JLS 17.5.3所说的)。

允许内联的一种情况(如果JIT编译器可以处理它)是一个局部变量,它是final或者有效的final,并且具有JIT编译器可以推导出的初始化器始终是相同的。总体约束是运行时内联不得更改程序的可观察行为。 (我们不需要考虑这里的反射,因为无法通过反射访问或更改局部变量。)

答案 2 :(得分:0)

根据您的需要,常量可以是私有或公共的,但您应该使用static + final。

因此...

private static final

或者...

public static final

答案 3 :(得分:0)

标记为static final的任何字段都无法在运行时更改*,即使使用反射也会被内联。

*需要注意的是,我相信您可以通过unsafe操作执行此操作。