1.编译期常量和运行时常量:
1.1.编译期常量 public static final int A1=2;//编译期就确定A1对应的数值,并把A1的相关引用都会直接替换成其对应的数值2
1.2.运行期常量 public static final int A1="hello".length();//在运行时才能确定具体数值
public class Test {
public static void main(String[] args) {
System.out.println(A.A1);
//A1变量可以被调用是因为 A1=2; 在编译期 确定并存储到内存的(内存中有A1)
}
}
class A{
public static final int A1=2;//编译期常量: 编译期 确定并存储到内存的
//public static int A1=2;//静态变量
static {//对A实例化的时候//不执行是因为没有new A
System.out.println("static block");
}
}
遇到new、getstatic或invokestatic这几条字节码指令时,如果类没有初始化,则需要先触发其初始化。生成这4条指令的最常见的Java代码场景是:
(1)使用new关键字实例化对象时
(2)读取或设置一个类的静态字段(被final修饰、已在编译期把结果放入常量池的静态字段除外)时//调用静态变量时
(3)调用一个类的静态方法时
以上内容摘抄自《深入理解Java虚拟机》7.2节 类加载的时机
2.根据程序运行结果,我们就可以得出结论了:编译期常量不依赖类,不会引起类的初始化;而运行时常量依赖类,会引起类的初始化。
3 编译时常量使用的风险
由于编译时,常量会被替换为字面量,这是JVM提高运行效率优化代码的一种方式,但有时候也会带来一定的麻烦。
如果我们项目超大,项目整个编译一次特别耗费时间,那么我们有可能会只编译代码修改的部分。而一旦我们修改了常量A,但又未重新编译所有引用A常量的部分(即.java文件),那么就会导致未重新编译的那部分代码继续使用A的旧值。
下面写个非常简单的实验看看。
定义常量的Book类:
public class Book {
//编译期常量,书本价格10元
public static final int price = 10;
}
定义Student类和mian方法:
public class Student {
public int cost = Book.price;
public void printCost() {
System.out.println("书费"+this.cost+"元");
}
public static void main(String[] args) {
Student stu = new Student();
stu.printCost();
}
}
/* 打印输出:
* 书费10元
*/
现在修改Book.java文件中的price=5,并使用javac命令仅仅只重新编译Book.java文件:
javac Book.java
执行java命令,再次运行main方法:
java Student
观察结果:结果与第一次相同,书费10元
————————————————
版权声明:本文为CSDN博主「Rhine404」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_34802416/article/details/83548369