访问类的静态属性与类的初始化

访问类的静态属性与类的加载


1. 访问类的静态变量

现有SuperClass类,其源码如下:

public class SuperClass {
    public static String staticVariable = "staticVariable";
    public static final String STATIC_CONSTANT = "STATIC_CONSTANT";

    static {
        System.out.println("SuperClass is loading.");
    }
}

现有一段代码,访问SuperClass类中的静态变量staticVariable:

public class MainClass {
    static {
        System.out.println("MainClass is loading.");
    }

    public static void main(String[] args) {
        // 访问类的静态变量
        System.out.println(SuperClass.staticVariable);
    }
}

上述代码执行后,控制台输出为:

MainClass is loading.
SuperClass is loading.
staticVariable

从代码的执行结果看,对类的静态变量的引用将会触发类的初始化过程

2. 访问类的静态常量

现有一段代码,访问SuperClass类中的静态常量STATIC_CONSTANT:

public class MainClass {
    static {
        System.out.println("MainClass is loading.");
    }

    public static void main(String[] args) {
        // 访问类的静态常量
        System.out.println(SuperClass.STATIC_CONSTANT);
    }
}

上述代码执行后,控制台输出为:

MainClass is loading.
STATIC_CONSTANT

从代码的指定结果看,对类的静态常量的引用不会触发类的初始化过程

从源码看,MainClass类直接引用了SuperClass类的静态常量,但经过编译阶段的“常量传播优化”后,该静态常量的值“STATIC_CONSTANT”已经被存储到了MainClass类自己的常量池中,MainClass类对该静态常量的引用也被修改成了对自身常量池的引用。换句话说,经过编译后,MainClass类与SuperClass类已经不存在任何联系了,MainClass类的字节码文件中,不存在SuperClass类的符号引用入口。

3. 访问父类的静态变量

现有SuperClass类的子类SubClass,其源码如下:

public class SubClass extends SuperClass{
    static {
        System.out.println("SubClass is loading.");
    }
}

现有一段代码,通过SubClass类调用SuperClass类的静态变量:

public class MainClass {
    static {
        System.out.println("MainClass is loading.");
    }

    public static void main(String[] args) {
        // 调用父类的静态变量
        System.out.println(SubClass.staticVariable);
    }
}

上述代码执行后,控制台输出为:

MainClass is loading.
SuperClass is loading.
staticVariable

从上述代码的执行结果看,通过子类引用父类的静态变量,并没有触发子类的初始化过程。其实,Java虚拟机规范中并未明确规定,对父类静态变量的引用是否要触发子类的初始化,这是由具体的虚拟机实现来决定的。

在上述代码的基础上,添加语句输出代码运行时的虚拟机环境信息:

public class MainClass {
    static {
        System.out.println("MainClass is loading.");
    }

    public static void main(String[] args) {
        System.out.println(SubClass.staticVariable);
        System.out.println("Java 虚拟机实现名称:" + System.getProperty("java.vm.name"));
        System.out.println("Java 虚拟机实现版本:" + System.getProperty("java.vm.version"));
    }
}
MainClass is loading.
SuperClass is loading.
staticVariable
Java 虚拟机实现名称:Java HotSpot(TM) 64-Bit Server VM
Java 虚拟机实现版本:25.171-b11

从控制台输出可以看出,当前我使用的是HotSpot虚拟机。

4. 访问父类的静态常量

现有一段代码,通过SubClass类访问父类SuperClass类的静态常量:

public class MainClass {
    static {
        System.out.println("MainClass is loading.");
    }

    public static void main(String[] args) {
        System.out.println(SubClass.STATIC_CONSTANT);
    }
}

代码执行后的控制台输出:

MainClass is loading.
STATIC_CONSTANT

从上述代码的执行结果,与上文“ 2. 访问类的静态常量 ”处代码的执行结果相同。

原文地址:https://www.cnblogs.com/XiaoZhengYu/p/13190439.html