教程:https://www.bilibili.com/video/av47756459
笔记中P4等表示视频中的第几P
Java虚拟机生命周期结束
- 执行了System.exit();
- 程序正常执行结束
- 程序执行过程中遇到异常或者错误
- 由于操作系统出错而导致Java虚拟机进程终止
P4
类:加载-连接-初始化
加载:查找并加载类的二进制数据
连接:
- -验证:确保被加载类的准确性
- -准备:为类的静态变量分配内存,并将其初始化为默认值。比如
public static int i = 1;
这个时候初始为0,并没有将1赋值给i。 - -解析:将类中的符号引用转化为直接引用
初始化:为类的静态变量赋予正确的初始值。即上面的1赋给i
使用 (主动使用 被动使用)
卸载
P5
主动使用与被动使用的代码例子 被动使用不会导致类的初始化
public class MyTest1 {
public static void main(String[] args){
System.out.println(Child.str1);
//System.out.println(Child.str2);
}
}
class Parent{
public static String str1 = "parent";
static {
System.out.println("parent block");
}
}
class Child extends Parent{
public static String str2 = "child";
static {
System.out.println("child block");
}
}
运行结果
parent block
parent
对于静态字段来说,只有直接定义了该字段的类才会被初始化。
所以打印Child.str1,由于继承的父类的字段,此时初始化的是父类,故打印父类代码块。
System.out.println(Child.str2);
parent block
child block
child
当一个类在初始化时,要求父类全部初始化完毕
P6
final关键词
将Child中的str2加上final关键词修饰
class Child extends Parent{
public static final String str2 = "child";
static {
System.out.println("child block");
}
}
结果:
child
原因: 常量在编译阶段会存入调用这个常量的方法所在的类的常量池中,此例子为 常量 Child中的str2,调用这个常量所在方法 mian方法,所在的类的常量池中 MyTest 的常量池中。本质上,调用类并没有直接引用到定义常量的类,因此并不会触发定义常量的类的初始化,即Chile类的初始化和Parent类的初始化。
若常量不是编译期可以确定的值,则会导致类的初始化。
public static final String str2 = UUID.randomUUID().toString();
当一个接口在初始化时,并不要求其父接口都完成初始化。
只有在真正使用到父接口的时候,(如引用接口中所定义点的常量时)才会初始化。