JVM中类的初始化时机
程序员文章站
2022-05-21 19:27:59
...
只有对类进行主动引用,才会触发其初始化方法,而除此之外的引用方式称之为被动引用,不会触发其初始化方法
1.主动引用
这里先定义一个Utils(名字随便起的,不要见怪)作为被测试类
package day12;
/**
* @author :weihuanwen
* @date :Created in 2019/5/23 00:14
* @description :
* @version: 1.0
*/
public class Utils {
//定义静态final变量
public static final int sfVar = 100;
//定义实例变量
public int instanceVar = 1;
//定义静态变量
public static int staticVar = 10;
//通过静态代码块是否执行验证此类是否加载
static {
System.out.println("Utils类被加载!");
}
/**
* 定义静态方法
*/
public static void staticMethod(){
System.out.println("执行了静态方法!");
}
/**
* 定义成员方法
*/
public void instanceMethod(){
System.out.println("执行了成员方法");
}
}
①设置静态成员变量时
package day12;
public class test01 {
public static void main(String[] args) {
Utils.staticVar = 10;
}
}
输出结果显示:
Utils类被加载!
②调用静态方法时
package day12;
public class test01 {
public static void main(String[] args) {
Utils.staticMethod();
}
}
输出结果显示:
Utils类被加载!
执行了静态方法!
③实例化对象时
package day12;
public class test01 {
public static void main(String[] args) {
Utils utils = new Utils();
}
}
输出结果显示:
Utils类被加载!
④读取静态成员变量时
package day12;
public class test01 {
public static void main(String[] args) {
System.out.println(Utils.staticVar);
}
}
输出结果显示:
Utils类被加载!
10
⑤反射调用时
package day12;
public class test01 {
public static void main(String[] args) throws ClassNotFoundException {
Class.forName("day12.Utils");
}
}
输出结果显示:
Utils类被加载!
⑥初始化子类时,会先初始化其父类
package day12;
/**
* 父类
*/
public class SuperClass {
static {
System.out.println("父类被加载!");
}
}
package day12;
/**
* 子类
*/
public class SubClass extends SuperClass{
static {
System.out.println("子类被加载!");
}
}
package day12;
public class test01 {
public static void main(String[] args){
new SubClass();
}
}
输出结果显示:
父类被加载!
子类被加载!
⑦Java虚拟机启动时被标明为启动类的类(含main()方法的类)
package day12;
public class Mark {
static {
System.out.println("标记类Mark被加载!");
}
public static void main(String[] args) {
//这里不写代码,直接自行该main()方法
}
}
class ReferFirst{
static {
System.out.println("第一个参照类被加载!");
}
}
class ReferSecond{
static {
System.out.println("第二个参照类被加载!");
}
}
输出结果显示:
标记类Mark被加载!
2.被动引用:
除了以上七种情况外的都尊徐被动引用,这里只介绍几种被动引用
①通过子类引用父类的静态字段,不会导致子类的初始化
package day12;
/**
* 父类
*/
public class SuperClass {
public static int staticVar = 10;
static {
System.out.println("父类被加载!");
}
}
package day12;
/**
* 子类
*/
public class SubClass extends SuperClass{
static {
System.out.println("子类被加载!");
}
}
package day12;
public class test01 {
public static void main(String[] args){
System.out.println(SubClass.staticVar);
}
}
输出结果显示:
父类被加载!
10
②读取static final 修饰的变量时,不会导致类的初始化
package day12;
public class test01 {
public static void main(String[] args){
System.out.println(Utils.sfVar);
}
}
输出结果显示:
100
****常量在编译阶段会存入调用类的常量池中,本质没有直接引用到定义的常量类中,因此不会触发定义的常量类初始化
③通过数组定义来引用,不会导致类的初始化
package day12;
public class Person {
static {
System.out.println("Person类被加载!");
}
}
package day12;
public class test01 {
public static void main(String[] args){
Person[] personarr = new Person[10];
}
}
输出结果显示:
无输出结果
④通过集合定义来引用,不会导致类的初始化(道理同③)
上一篇: java类初始化时机
下一篇: 图的深度优先遍历和广度优先遍历