类初始化学习笔记

类初始化

一.主动引用:

  • 遇到new、getstatic、putstatic或者invokestatic这4条字节指令,如果类没有被初始化过,则会触发类的初始化。也就是说下列情况:
    • new关键字实例化对象
    • 读取或者设置一个类的静态字段(静态常量除外)
    • 调用一个类的静态方法
  • 使用java.lang.reflect包的方法对类进行反射调用的时候。如果类没有被初始化过,则会触发类的初始化。
  • 当初始化一个类的时候,发现其父类还未初始化,则先触发父类的初始化。
  • 虚拟机启动时,先初始化主类。

二.被动引用:

1.子类引用父类的静态变量,不会引起子类的初始化.

对于静态字段,只有直接定义这个字段的类才会进行初始化。

public class SuperClass{
    static{
        System.out.println("SuperClass init...");
    }
    public static int value = 123;
}

public class SubClass extends SuperClass{
    static{
        System.out.println("SubClass init...");
    }
}

public class Test{
    public static void main(String[] args){
        System.out.println(SubClass.value);
    }
}

输出结果为: SuperClass init…

2.对常量的引用,不会引起初始化。

因为常量在编译的时候已经将常量放入调用类的常量池里面。假如A调用B的常量c,经过编译后,常量c已经是A常量池中的常量,Class文件中没有两个类关联的信息,也就是在编译后AB没有任何联系,所以不会引起初始化。

public class ConstClass{
    static{
        System.out.println("ConstClass init...");
    }
    public static final String S = "Const";
}

public class Test{
    public static void main(String[] args){
        System.out.println(ConstClass.S);
    }
}

没有任何输出结果。

3.通过数组定义来引用类,不会触发初始化。

虽然不会初始化我们定义的类,但是会初始化一个由字节码指令newarray触发生成的一个类。

public class ArrayTest{
    static{
        System.out.println("ArrayTest init...");
    }
}

public class Test{
    public static void main(String[] args){
        ArrayTest[] array = new ArrayTest[5];
    }
}

没有任何输出结果。

三.针对接口的说明

主要不同点是,类在初始化的时候要求其父类都初始化过。而接口在初始化的时候并不要求父类接口初始化,只有在真正用到父接口的时候才初始化。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值