流程
- graph LR
- 加载-->验证
- 验证-->准备
- 准备-->解析
- 解析-->初始化
- 初始化-->使用
- 使用-->卸载
ada
初始化
java虚拟机规范,所有java虚拟机实现必须在每个类或接口被java程序首次主动使用时才初始化。
主动使用的几种情况:
- 创建类的实例
- 访问某个类或者接口的静态变量,或者对该静态变量赋值(如果访问静态编译时常量(即编译时可以确定值的常量)不会导致类的初始化)
- 调用类的静态方法
- 反射(Class.forName(xxx.xxx.xxx))
- 初始化一个类的子类(相当于对父类的主动使用)
- Java虚拟机被标明为启动类的类(包含main方法的)
看下面的实例
- package chapter7.classload.initialization;
- public class TestClass {
- private String name;
- public static final int price=10;
- static {
- System.out.println("Initializing");
- }
- TestClass() {
- System.out.println("Building");
- }
- TestClass(String name) {
- this.setName(name);
- }
- public static String playToy(String player) {
- String msg = player + " plays " ;
- System.out.println(msg);
- return msg;
- }
- public void setName(String name) {
- this.name = name;
- }
- }
processing
测试类:
- package chapter7.classload.initialization;
- public class RunTest1 {
- public static void main(String[] args) throws ClassNotFoundException {
- // 对上面的类,执行下面的代码:
- Class<?> c = Class.forName("chapter7.classload.initialization.TestClass");
- // c.newInstance();
- }
- }
aspectj
输出:
- Initializing
问题
初始化时仅会初始静态代码块(static{}块中)的语句和所有类变量的赋值动作,以下面代码为例,输出结果B的值为2
- static class Parent {
- public staic int A = 1;
- static {
- A = 2;
- }
- }
- static class Sub extends Parent {
- public static int B = A;
- }
- public static void main(String[] args) {
- System.out.println(Sub.B);
- }
java
分析
Parent是Sub的父类,查看本文开头的规范初始化一个类的子类(相当于对父类的主动使用),所以会初始化Parent类,但初始化时仅会初始化静态代码和类变量赋值,所以,会执行static {
A = 2;
}
, 所以B = 2了
Comments