4、访问常量是否会引起类的初始化?

访问常量是否会引起类的初始化,关键要看常量的值是否在编译期间可以确定。

  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); //输出 //Parent2 static block
     //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"); } }

 

posted @ 2020-02-18 18:04  java小天地  阅读(543)  评论(0)    收藏  举报