类的声明周期
加载(loading) -> 链接(linking) -> 初始化(initialization) -> 使用(Using) -> 卸载(unloading)
链接(linking):验证(verification) -> 准备(preparation) -> 解析(Resolution)
初始化
父类静态变量、父类静态初始化块 -> 子类静态变量、子类静态初始化块 -> 子类main方法 -> 父类变量、父类初始化块 -> 父类构造器 -> 子类变量、子类初始化块 -> 子类构造器
创建过程
例:
public class Test002 {
public static void main(String[] args) {
System.out.println("----------------------main----------------------");
Student student = new Student();
System.out.println("----------------------main----------------------");
student.study();
}
}
public class Person {
private static final String NAME = "父类";
private String name;
private int age = 10;
private static String attribute = "父类静态变量 ->" + NAME;
public Person(){
System.out.println("父类 -> 构造器");
}
static {
System.out.println("父类静态变量 ->" + attribute);
System.out.println("父类 -> 静态代码块");
}
{
System.out.println("父类静态变量 ->" + age);
System.out.println("父类 -> 代码块");
}
public void walk() {
System.out.println("走路.....");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
public class Student extends Person {
private static final String NAME = "子类";
private String level = "高一";
private static String attribute = "子类静态变量 -> " + NAME;
public Student(){
System.out.println("子类 -> 构造器");
}
static {
System.out.println("子类 -> " + attribute);
System.out.println("子类 -> 静态代码块");
}
{
System.out.println("子类 -> " + level);
System.out.println("子类 -> 代码块");
}
public void study() {
System.out.println("学习.....");
}
public String getLevel() {
return level;
}
public void setLevel(String level) {
this.level = level;
}
}
-
JVM去方法区找Test002类的代码信息,如果找到,直接使用,找不到则通过类加载器进行加载,加载完成后会将类信息(构造方法、接口定义)、静态变量、常量信息放入方法区。运行时常量池也在方法区放置,每个对象有自己的常量池。调用main方法时,将main方法放入到栈中。
-
执行main方法,执行Student student = new Student();
-
JVM会去方法区找Student类的代码信息,如果找到,则直接调用,没有找到的话,则通过类加载器进行加载。加载完成后,将类信息、静态变量、常量信息放入方法区
- 加载Student和父类的Class文件,生成Class对象
- 校验Student和父类Class文件是否符合JVM规范
- 进行静态变量内存的申请以及值的初始化(0、null)
- 将常量符号引用转化为直接引用
- 理解:将常量值放入到运行时常量池,将引用赋值给属性
-
在main方法栈中声明student变量
-
进行Student对象的初始化 - new Student()
-
在堆中为对象开辟一个内存
-
进行对象的初始化
父类静态变量 ->父类静态变量 ->父类 父类 -> 静态代码块 子类 -> 子类静态变量 -> 子类 子类 -> 静态代码块 父类静态变量 ->10 父类 -> 代码块 父类 -> 构造器 子类 -> 高一 子类 -> 代码块 子类 -> 构造器
-
-
将初始化完成后的Student对象地址赋值给栈中的student局部变量
-
-
执行student.study()方法,去方法区调用该方法
参考: