访问常量是否会引起类的初始化,关键要看常量的值是否在编译期间可以确定。
1)如果常量的值可以在编译期间确定,则访问该常量时不会引起常量所在类的初始化;
如:public static final String a = "parent";
原因:常量的值在编译期间可以确定,则在编译阶段就会将【常量a的值】存入到调用方法所在类的常量池中。本质上,调用常量的类并没有直接引用到定义常量的类,
因此并不会触发定义常量类的初始化。
2)如果常量的值不可以在编译期间确定,则访问该常量时会引起常量所在类的初始化;
如:public static final String b = UUID.randomUUID().toString();
原因:因为常量的值在编译期间无法确定,所以在编译阶段并不会将【常量b的值】存入到调用方法所在类的常量池中。因此程序在运行时,会主动使用常量b所在的类,
导致该类的初始化。
package com.shtec.init; import java.util.UUID; /** * 【确定值的常量】在编译阶段会存入到调用这个常量的方法所在的类的常量池中,本质上,调用常量的类并没有直接引用到定义常量的类,因此并不会触发定义常量类的初始化。 * Parent2类中的【常量a】在编译阶段就已经放到了Demo2的常量池中,因此并不会将Parent2中的静态代码块打印出来 * * @author sunhao * */ public class Demo2 { public static void main(String[] args) { //编译阶段就会将a的值parent存入到Demo2的常量池中,所以在调用【Parent2.a】时,是直接从Demo2的常量池中取值,不会触发Parent2的初始化; System.out.println(Parent2.a); //输出 //parent //编译阶段无法将b的值存入到Demo2的常量池中,所以在调用【Parent2.b】时,会主动使用Parent2这个类,因此会触发Parent2的初始化; System.out.println(Parent2.b); //输出 //parent //e28f2c68-204e-474d-be01-cbda912a4836 } } class Parent2{ public static final String a = "parent"; public static final String b = UUID.randomUUID().toString(); static{ System.out.println("Parent2 static block"); } }
原文:https://www.cnblogs.com/sunhao1234/p/12327303.html