java是一门静态语言(先编译,再执行),但是它同时具有很多动态语言的特性。java 中类的加载,连接,初始化是程序在运行期间完成的。
- 加载 : 将编译后的class文件加载到内存。加载的方式有
- 从本地系统直接加载class文件
- 通过网络远程加载class文件
- 从zip,jar中加载class文件
- 程序运行期间动态将源文件加载成class文件,参照java设计模式中的动态代理
- 连接 : 连接分为三个阶段
- 验证:验证class文件是否符合jvm规范,因为class文件可以被人为篡改。
- 准备:类的静态变量分配内存空间,并赋默认值。(比如int的默认值是0,引用对象的默认值是null)
- 解析 : 符号引用转换成直接引用。
- 初始化:类的静态变量赋值;执行类的静态代码块 static{ }
类的初始化场景:类在主动引用的时候会执行初始化,以下场景是类的主动引用
- 创建类的实例,即创建对象
- 访问或者修改类的静态变量
- 调用类的静态方法
- 反射
- 初始化一个类的子类(会先初始化父类)
/** * Created by IntelliJ IDEA. * User: chenzhubing * Date: 2019/6/16 */ public class ClassInitTest { public static void main(String[] args) { System.out.println(Child.str1); } } class Parent{ static String str1 = "hello"; static{ System.out.println("parent static block....."); } } class Child extends Parent{ static String str2 = "world"; static{ System.out.println("child static block......."); } }
分析下:
- 访问Child.str1会执行类的初始化,会执行类的静态代码块内容
- 对于静态变量,只有直接定义了该变量的类才会被初始化。因此Child类不会执行初始化
- 输出结果:
parent static block.....
hello
/** * Created by IntelliJ IDEA. * User: chenzhubing * Date: 2019/6/16 */ public class ClassInitTest { public static void main(String[] args) { System.out.println(Child.str2); } } class Parent{ static String str1 = "hello"; static{ System.out.println("parent static block....."); } } class Child extends Parent{ static String str2 = "world"; static{ System.out.println("child static block......."); } }
分析下:
- 访问Child.str2会执行Child类的初始化,由于它继承Parent,因此会先执行Parent初始化
- 输出结果:
parent static block.....
child static block.......
world