-
记载:就是把二进制形式的java类型读入java虚拟机中
-
验证:
-
准备:为类变量分配内存,设置默认值。但是在到达初始化之前,类变量都没有初始化为真正的初始值
-
解析:解析过程就是在类型的常量池中寻找类、接口,字段和方法的符号引用,把这些符号引用替换成直接引用的过程。
-
初始化:为类变量赋予正确的初始值。
-
类实例化:
- 为新的对象分配内存。
- 为实例变量赋默认值。
- 为实例变量赋正确的初始值。
-
java编译器为它编译的每一个类都至少生成一个实例初始化方法,再java的class文件中,这个实例初始化方法被称为“<init>”。针对源代码中每一个类的构造方法,java编译器都产生一个<init>方法。
-
类的加载的最终产品是位于内存中的class对象
类的加载
- JVM规范允许类加载器在预料某个类将要被使用时就预先加载它,如果在预先加载的过程中遇到.class文件缺失或存在错误,类加载器必须在程序首次主动使用该类是才会报告错误(LinkageError错误)
- 如果这个类一直没有被程序主动使用,那么类加载器就不会报告错误。
类的初始化规则
- 当java虚拟机初始化一个类时,要求它的所有父类都被初始化,但是这条规则并不适用与接口。
- 在初始化一个类时,并不会先初始化它所实现的接口。
- 在初始化一个接口时,并不会先初始化它的父接口。
因此,一个父接口并不会因为它的子接口或者实现类的初始化而初始化,只有当程序首次使用特定接口的静态变量时,才会导致该接口的初始化。
/**
* @author NingXioaoming
* @createTime 2019/12/12 15:13
* @description
*/
/*
一个父接口并不会因为它的子接口或者实现类的初始化而初始化,
只有当程序首次使用特定接口的静态变量时,才会导致该接口的初始化
*/
public class MyTest5 {
public static void main(String[] args) {
System.out.println(MyChild5.bb);
/* new c();
new c();*/
}
}
interface MyParent5{
String bb = UUID.randomUUID().toString();
// static int c = 1/0;
static int a = 4;
Thread t = new Thread(){
{
System.out.println("MyParent5 run");
}
};
}
class MyChild5 implements MyParent5{
public static final String bbc = UUID.randomUUID().toString();
public static final int b= 5; //默认为 static和final的
}
class c{
public c(){//第三执行
System.out.println("无参构造 run");
}
{//第二执行
System.out.println("nihao");
}
static {//先执行
System.out.println("static 块 run");
}
}
类加载器
1. 双亲(父亲,爷爷)委托加载类机制
image.pngimage.png
由下往上进行加载 只要有一个类加载器加载成功,就加载成功了, 下面加载不成功 则给上面的双亲让双亲进行加载。
网友评论