- 加载 根据路径找到想对应的class文件 并将这个文件加载到Java虚拟机中(存储到方法区内)
类加载分为隐式类加载和显示类加载 隐式类加载是指在层程序使用new关键词创建的对象时, 会隐式的调用类的加载器把对应的类加载到JVM中. 显示类加载指的是通过直接调用class.forName() 方法把所需要的类加载到JVM中
-
检查: 检查类加载的class文件的正确性(文件格式检验 元数据验证 字节码验证 符号引用验证)
-
准备: 给类加载的静态变量分配内存空间并赋予初始默认值
-
解析: 虚拟机将常量池中的符号引用替换成直接引用得过程, 符号引用就可以理解为一个标识 而在直接引用就可以直接指向内存中的地址
-
初始化: 为静态变量和静态代码块指向初始化工作(执行静态代码块和静态变量)
什么时候会触发类加载(重点)
-
构造该类的实例的时候
-
调用该类的静态属性或方法的时候
-
使用子类时会触发父类的加载
经典题目
/**
-
Created with IntelliJ IDEA.
-
Description: If you don’t work hard, you will a loser.
-
User: Listen-Y.
-
Date: 2020-08-04
-
Time: 15:34
*/
class One {
public One() {
System.out.println(“One 构造”);
}
{
System.out.println(“One 实例”);
}
static {
System.out.println(“One 静态”);
}
}
class Two extends One {
public Two() {
System.out.println(“Two 构造”);
}
{
System.out.println(“Two 实例”);
}
static {
System.out.println(“Two 静态”);
}
}
public class Demo1 extends Two{
public static void main(String[] args) {
System.out.println(“开始”);
new Two();
new Two();
System.out.println(“结束”);
}
}
结果为:
One 静态
Two 静态
开始
One 实例
One 构造
Two 实例
Two 构造
One 实例
One 构造
Two 实例
Two 构造
结束
- 分析:
-
代码从main方法开始执行 main方法是Demo的静态方法 就会触发Demo的类加载
-
Two是Demo的父类 所以在加载Demo前会先加载Two 但是呢one又是Two的父类 就又会优先加载
-
加载One的静态代码块输出 One静态
-
加载Two的静态代码块 输出 Two静态
-
Demo没有静态代码块了就会执行main方法的内容 输出 开始
-
在构造Two的实例的时候会先构造One的实例 就会先执行One的代码块和构造方法 然后才执行Two的代码块和构造方法 所以输出One实例 One构造 Two实例 Two构造
-
进行第二次构造Two的时候和第一次构造一样输出One实例 One构造 Two实例 Two构造
-
最后打印结束
- 如果我们稍微改一下代码让Demo不继承Two会发生怎样的情况
/**
-
Created with IntelliJ IDEA.
-
Description: If you don’t work hard, you will a loser.
-
User: Listen-Y.
-
Date: 2020-08-04
-
Time: 15:34
*/
class One {
public One() {
System.out.println(“One 构造”);
}
{
System.out.println(“One 实例”);
}
static {
System.out.println(“One 静态”);
}
}
class Two extends One {
public Two() {
System.out.println(“Two 构造”);
}
{
System.out.println(“Two 实例”);
}
static {
System.out.println(“Two 静态”);
}
}
public class Demo1{
public static void main(String[] args) {
System.out.println(“开始”);
new Two();
new Two();
System.out.println(“结束”);
}
}
结果:
开始
One 静态
Two 静态
One 实例
One 构造