Skip to content

主动使用:类只有在首次主动使用时才会被加载,而在首次使用被加载时,必须进行初始化。

以下使用被认为是主动使用: 1、当创建一个类的实例时,比如使用 new 关键字,或者通过反射、克隆、反序列化

2、当调用类的静态方法时,即当使用了字节码 invokestatic 指令

3、当使用类、接口的静态字段时(final 修饰特殊考虑),比如,使用 getstatic 或者 putsttic 指令。(对应访问变量、赋值变量操作)

4、当使用 java.lang.reflect 包中的方法反射类的方法时。比如:Class.forname("com.atguigu.java.Test")

5、当初始化子类时,如果发现其父类还没有进行过初始化,则需要先触发其父类的初始化

6、如果一个接口定义了 default 方法,那么直接实现或者间接实现该接口的类的初始化,该接口要在其之前被初始化

7、当虚拟机启动时,用户需要指定一个要执行的主类(包含 main() 方法的那个类),虚拟机会先初始化这个主类

8、当初次调用 MethodHandle 实例时,初始化该 MethodHandle 指向的方法所在的类。(涉及解析 REF_getStatic、REF_putStatic、REF_invokeStatic 方法句柄对应的类)

注意: 1、当Java 虚拟机初始化一个类时,要求它的所有父类都已经被初始化,但是这条规则并不适用于接口在初始化一个类时,并不会先初始化它所实现的接口 在初始化一个接口时,并不会先初始化它的父接口。因此,一个父接口并不会因为它的子接口或者实现类的初始化而初始化,只有当程序首次使用特定接口的静态字段时,才会导致该接口的初始化 2、JVM 启动的时候通过引导类加载器加载一个初始类。这个类在调用 public static void main(String[]) 方法之前被链接和初始化。这个方法的执行将依次导致所需的类的加载、链接和初始化

被动使用:除了以上的情况属于主动使用,其他的情况均属于被动使用。被动使用不会引起类的初始化。也就是说:并不是在代码中出现的类,就一定会被加载或者初始化。如果不符合主动使用的条件,类就不会初始化。

1、当访问一个静态字段时,只有真正声明这个字段的类才会被初始化

2、当通过子类引用父类的静态变量,不会导致子类初始化

3、通过数组定义类引用,不会触发此类的初始化

4、引用变量不会触发此类或接口的初始化。因为常量在链接阶段就已经被显式赋值了

5、调用 ClassLoader 类的 loadClass() 方法加载一个类,并不是对类的主动使用,不会导致类的初始化

Released under the MIT License.