java编译期常量

下面两段代码的输出:

//
public class Test {
    public static void main(String[] args) {
        System.out.println(Test2.a);
    }
}


//字面量
public class Test2 {
    static {
        System.out.print("OK");
    }

    public static final String a= "JD";
}

//new对象
public class Test2 {
    static {
        System.out.print("OK");
    }

    public static final String a= new String("JD");
}

字面量输出:JD

new对象输出:OKJD

为什么呢?他俩的区别就是,执行static块!!那么什么时候会执行 static 块呢?答案肯定是 类加载的时候。通过简单的结论:字面量当外部类,未加载类。

那么问题又来了,为什么未加载呢?这个时候,编译器常量 应该可以解除你的疑惑。只需要弄明白,什么是编译期常量!!!!

--------------------------------------

参考:https://www.cnblogs.com/Vdiao/p/6040125.html

   http://www.cnblogs.com/ningvsban/p/3591610.html

看了上边两篇文章,你应该是,常量分为 编译期常量运行时常量

编译期常量:它的值在编译期就可以确定的常量

例如:

    public static final String a= "JD";

运行时常量:只有在运行时,通过加载类之后才能确定其值,值的初始化是在类加载的过程中。

例如:

    public static final String a= new String("JD");

通过 new 对象,此时 a 存储的是 String 对应实例对象 的引用,只有在在运行的时候,才可以在加载类之后,通过初始化之后,才会在堆中创建对象,从而得到对象的引用,赋值给 a。

对于字面量的a,它在编译的时候,编译器就可以确定其值,并将其被引用的地方,等价替换。也就不需要后续的类的加载,也算是一种性能优化! 

----------------------------------------------------------------
从另外一个角度看,咱们看反编译后,字节码文件里边的现象:

当引用字面量的常量字符串,这个时候,编译器在编译的时候,通过计算得出相同的值,等价替换。

当如果是new对象,这时候,对应的调用 Test2类中的 gestatic(),此时则需要加载 Test2 类。

Read the fucking manual and source code
原文地址:https://www.cnblogs.com/qxynotebook/p/9627093.html