🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
[TOC] # 1、概念: ## 1.1类的加载阶段 ![](https://box.kancloud.cn/d0aa6f298ae286faf5037cbf31afe3c8_608x236.png) 使用某类时,如果类还没有加载到内存,则系统会**加载**、**连接**、**初始化**三个步骤对类进行初始化。通常由jvm完成这三个步骤。这三个步骤统称为类加载或类初始化。 > **1、将类的class文件读入内存,并为之创建一个java.lang.Class对象。** 也就是说使用一个类时,都会先进行一次(且只有一次)类的加载。 > 2、类的加载由加载器完成,加载器通常由jvm提供 ### 1.1.2 类加载源 可以通过以下文件加载: 1. class文件 2. jar文件 3. 通过网络加载class文件 4. 动态编译java源文件,并加载 ### 1.1.3 类: > 类,是一类对象的抽象,是一个概念层次上的东西,但是java中一切皆为对象,类也不例外是java.lang.Class的实例。 > java.lang.Class即为类这个对象的抽象(描述) ## 1.2 类的连接阶段 ### 1. 当类被加载之后,系统为之生成对应的Class对象,接着就会进入**连接阶段**。连接阶段负责将类的二进制数据合并到jre当中去。 ### 2. **连接分为三个阶段:** 1) 验证阶段 验证加载的类是否有正确的内部结构,并且与其他类协调一致。 2) 准备阶段 负责为类的类变量分配内存,并设置默认初始值。 3) 解析阶段 将类的二进制数据中的符号引用替换成直接引用。 ## 1.3 类的初始化阶段 ### 1.3.1 初始化过程 > 1、该阶段有jvm负责对类进行初始化,主要是对类变量进行初始化。 > 2、java对类变量指定初始值有两种方式: > ---- 1)**声明类变量时指定初始值** > ---- 2)**静态初始化块对类变量指定初始值** > ---- 3)**如果没有显示的指定初始值,则初始化为默认值** > 3、**类初始化语句和静态初始化块安装定义的顺序执行** ``` public class Test { static { // 使用静态初始化块为变量b指定出初始值 b = 6; System.out.println("----------"); } // 声明变量a时指定初始值 static int a = 5; static int b = 9; // ① static int c; public static void main(String[] args) { System.out.println(Test.b); } } ``` ### 1.3.2 类初始化时机 **以下使用类或者接口时,都会引起类的初始化:** 1、当创建类的实例时(new 或者反射) 2、调用某类的类方法(静态方法) 3、调用某个类的或者接口的类变量,或者为类变量赋值 4、初始化某一个类的子类(初始化时,总是会先初始化父类) 5、使用java命令运行某个主类时,当运行某个主类时,程序会先初始化主类。 ### 1.3.2 final关键字与类初始化 > **1、对于一个final类型的类变量,如果该变量的值编译期时可确定下来,则这个类变量相当于一个“宏变量”。** > > 2、java编译器会在编译时,将这个类变量出现的地方替换成它的值,**因此,程序使用改类变量也不会引起类的初始化。** ``` class MyTest { static { System.out.println("静态初始化块..."); } // 使用一个字符串直接量为static final的类变量赋值 static final String compileConstant = "hello java"; } public class CompileConstantTest { public static void main(String[] args) { // 访问、输出MyTest中的compileConstant类变量 System.out.println(MyTest.compileConstant); // ① } } ``` 由于compileConstant这类变量有final关键字修饰,并且在编译时类变量的值就可以被确定下来(一个固定的字符串),所以