static final修饰的字段在javac编译时生成constantValue属性,在类加载的准备阶段直接把constantValue的值赋给该字段。可以理解为在编译期即把结果放入了常量池中。即在类未被加载时static final字段就有了值,这个值不需要对类进行初始化就可以读取,不像static变量,需要类加载后才会有值(类未加载进内存时值为默认值0或null)。
注:1.ConstantValue修饰的字段只限于基本类型和string。
2.ConstantValue修饰的字段若为String类型,必须要是编译期可以进行优化得到的即编译期常量才能满足不需要对类进行初始化就可以读取(例如:String s = “a”+“bc”;),否则这个值需要对类进行初始化才可以读取(例如:String s = new String(“abc”);)。
3.对于满足上两个条件的constantValue变量,在访问该变量时,无需初始化类即可访问(即访问时在常量池中寻找,不会执行类的静态成员和静态代码块)。
例1:
public class Test {
public static void main(String[] args) {
System.out.println(Test2.a);
}
}
class Test2{
public static final String a="JD";
static {
System.out.print("OK");
}
}
结果:“JD”
原因:Test2类中的a变量是ConstantValue类型的编译期常量,无需初始化Test2类就可以调用,因此不会触发静态代码块。
例2:
public class Test {
public static void main(String[] args) {
System.out.println(Test2.a);
}
}
class Test2{
public static final String a=new String("JD");
static {
System.out.print("OK");
}
}
结果:“OKJD”
原因:看上面的第二条注意事项,a变量不是常量,需要初始化类。
参考:https://www.cnblogs.com/hglibin/p/10298650.html https://blog.csdn.net/honjane/article/details/51835636