所谓编译期常量就是指程序在编译时,就可以确定这个常量的具体值 而非编译期常量就是指程序在运行时,才可以确定这个常量的具体值
下面请看具体代码
class FinalTest1{
public static final int a = 6;
static {
System.out.println("FinalTest1");
}
}
class FinalTest2{
public static final int a = new Random().nextInt(100);
static {
System.out.println("FinalTest2");
}
}
public class TestCompileConstant {
public static void main(String[] args) {
System.out.println(FinalTest1.a);
System.out.println(FinalTest2.a);
}
}
此程序运行结果为
6
FinalTest2
47
为什么“FinalTest1”没有被输出,好像违背了类加载的定义,即调用类的静态常量将引发类的加载,而这个程序“FinalTest1”却没有被输出出来。
这里就涉及到了一个编译期常量,public static final a = 6; 变量a 加上了final 修饰符并且直接赋值,这时这个值就不会被更改,在编译期就可以直接赋值,所以访问此静态变量就不需要重新加载类。这同时也解释了为什么我们在写String 常量的时候,一定要加final,因为这样类不必全部加载,节省内存空间。
而FinalTest2里的 变量a 赋值是一个随机数,你永远也不知道这个结果是什么,除非你运行之后,这类变量就是非编译期常量,调用它就是对类进行加载,从而触发static 代码块。同时,static代码块的执行,优于变量的访问,所以"FinalTest2"输出在前。