必须是private + static + final才能作为编译时常量内联吗?
什么可以作为运行时常量?
怎么样:
private final ...
static final ...
final ...
答案 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
操作执行此操作。