Java类的初始化和对象的初始化

类的初始化过程

类在使用之前会经过加载、连接、初始化三个步骤。

加载

将类的 class 文件读入内存,并为之创建一个 java.lang.Class 对象。

连接

连接又可以分为三个子步骤:

  • 连接:检验被加载的类是否有正确的内部结构;
  • 准备:为静态变量分配内存空间,并设置默认值;
  • 解析:在类型的常量池中寻找类、接口、字段和方法的符号引用,把这些符号引用替换成直接引用。这个阶段可以被推迟到初始化之后,当程序运行的过程中真正使用某个符号引用的时候 再去解析它。

初始化

初始化阶段主要就是对类变量进行初始化,在 Java 类中对类变量指定初始值有两种方式:

1) 声明类变量时指定初始值;
2) 使用静态初始化块为类变量指定初始值。

以上两者按照出现顺序执行。

类的初始化时机

1) 创建类的实例
2) 调用类的静态方法
3) 访问类或接口的类变量,或为类变量赋值
4) 使用反射方式强制创建类或接口对应的 java.lang.Class 对象
5) 初始化类的子类
6) 直接使用 java.exe 运行类

对象的初始化过程

根据类变量与静态初始化块的执行过程,可以感觉出成员变量与普通初始化块的执行过程。

成员变量指定初始值除了类变量的两种方式外,还可以在构造器中指定。

执行过程实例

// Grandpa
public class Grandpa {

    static {
        System.out.println("Grandpa 静态初始化块");
    }

    {
        System.out.println("Grandpa 普通初始化块");
    }

    Grandpa () {
        System.out.println("Grandpa 构造器");
    }

}

// Father
public class Father extends Grandpa {

    static {
        System.out.println("Father 静态初始化块");
    }

    {
        System.out.println("Father 普通初始化块");
    }

    Father () {
        System.out.println("Father 构造器");
    }

}

// Son
public class Son extends Father {

    static {
        System.out.println("Son 静态初始化块");
    }

    {
        System.out.println("Son 普通初始化块");
    }

    Son () {
        System.out.println("Son 构造器");
    }

    public static void main(String[] args) {
        Son s1 = new Son();
        Son s2 = new Son();
    }

}

// 结果
Grandpa 静态初始化块
Father 静态初始化块
Son 静态初始化块
Grandpa 普通初始化块
Grandpa 构造器
Father 普通初始化块
Father 构造器
Son 普通初始化块
Son 构造器
Grandpa 普通初始化块
Grandpa 构造器
Father 普通初始化块
Father 构造器
Son 普通初始化块
Son 构造器

一个测试

public class Test {

    static Test test = new Test();

    {
        System.out.println("normal");
    }

    static {
        System.out.println("static");
    }

    public static void main(String [] args){
        Test test = new Test();
    }

}

// 结果
normal
static
normal

你可能感兴趣的:(Java)