访问类的静态属性与类的加载
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. 访问类的静态常量 ”处代码的执行结果相同。