小白日更第三十八天->类初始化时机

14 篇文章 1 订阅

什么时候会发生类的初始化

1、创建类的实例,也就是new一个对象
2、访问某个类或接口的静态变量,或者对该静态变量赋值
3、调用类的静态方法
4、反射(Class.forName(“com.qcby.***”))
5、初始化一个类的子类(会首先初始化子类的父类)
6、JVM启动时标明的启动类,即文件名和类名相同的那个类
 测试:

创建类的实例,也就是new一个对象

package com.qcby.algorithm;

public class Test01 {
    public static void main(String[] args) {
        A a = new A();
    }
}
class A{
    A(){
        System.out.println("执行构造函数");
    }
    {
        System.out.println("执行代码块");
    }
    static {
        System.out.println("执行静态代码块");
    }
}

运行结果在这里插入图片描述
完善一下:

package com.qcby.algorithm;

public class Test01 {
    static {
        System.out.println("main所在的类进行初始化");
    }
    public static void main(String[] args) {
        B b = new B();
    }
}
class A{
    static int a;
    A(){
        System.out.println("父类执行构造函数");
    }
    {
        System.out.println("父类执行代码块");
    }
    static {
        System.out.println("父类执行静态代码块");
        a=10;
    }
}
class B extends A{
    static int b;
    B(){
        System.out.println("子类执行构造函数");
    }
    {
        System.out.println("子类执行代码块");
    }
    static {
        System.out.println("子类执行静态代码块");
        b=100;
    }
}

结果:
在这里插入图片描述
从运行结果我们可以看出当JVM虚拟机启动,先初始化main方法所在的类。当我么在new 一个类的对象,如果其父类没有被初始化,则会先初始化他的父类。加载顺序也一目了然了。先加载父类static代码块,然后是子类static代码块,然后是父类代码块,构造函数。子类代码块,构造函数。

访问某个类或接口的静态变量,或者对该静态变量赋值

package com.qcby.algorithm;

public class Test01 {
    static {
        System.out.println("main所在的类进行初始化");
    }
    public static void main(String[] args) {
        System.out.println(B.b);
//        System.out.println(B.b = 1);


    }
}
class A{
    static int a;
    A(){
        System.out.println("父类执行构造函数");
    }
    {
        System.out.println("父类执行代码块");
    }
    static {
        System.out.println("父类执行静态代码块");
        a=10;
    }
}
class B extends A{
    static int b;
    B(){
        System.out.println("子类执行构造函数");
    }
    {
        System.out.println("子类执行代码块");
    }
    static {
        System.out.println("子类执行静态代码块");
        b=100;
    }
}

代码运行结果
在这里插入图片描述
给静态变量复制的操作我在这里就不演示了哈,小伙伴们自己

调用类的静态方法

package com.qcby.algorithm;

public class Test01 {
    static {
        System.out.println("main所在的类进行初始化");
    }
    public static void main(String[] args) {
        A.study();
    }
}
class A{
    static int a;
    A(){
        System.out.println("父类执行构造函数");
    }
    {
        System.out.println("父类执行代码块");
    }
    static {
        System.out.println("父类执行静态代码块");
        a=10;
    }
    public static void study(){
        System.out.println("好好学习!");
    }
}

运行结果
在这里插入图片描述

反射(Class.forName(“com.qcby.***”))

package com.qcby.algorithm;

public class Test01 {
    static {
        System.out.println("main所在的类进行初始化");
    }
    public static void main(String[] args) throws Exception{
        Class<?> aClass = Class.forName("com.qcby.algorithm.B");
    }
}
class A{
    static int a;
    A(){
        System.out.println("父类执行构造函数");
    }
    {
        System.out.println("父类执行代码块");
    }
    static {
        System.out.println("父类执行静态代码块");
        a=10;
    }
    public static void study(){
        System.out.println("好好学习!");
    }
}
class B extends A{
    static int b;
    B(){
        System.out.println("子类执行构造函数");
    }
    {
        System.out.println("子类执行代码块");
    }
    static {
        System.out.println("子类执行静态代码块");
        b=100;
    }
}

一个注意点,要抛出一个异常,不然会报错

java: 未报告的异常错误java.lang.ClassNotFoundException; 必须对其进行捕获或声明以便抛出

很好理解,人家怎么知道你到底有没有这个类,要是没有就会抛出ClassNotFoundException。

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

package com.qcby.algorithm;

public class Test01 {
    static {
        System.out.println("main所在的类进行初始化");
    }
    public static void main(String[] args) {
       B.a=666;
    }
}
class A{
    static int a;
    A(){
        System.out.println("父类执行构造函数");
    }
    {
        System.out.println("父类执行代码块");
    }
    static {
        System.out.println("父类执行静态代码块");
        a=10;
    }
    public static void study(){
        System.out.println("好好学习!");
    }
}
class B extends A{
    static int b;
    B(){
        System.out.println("子类执行构造函数");
    }
    {
        System.out.println("子类执行代码块");
    }
    static {
        System.out.println("子类执行静态代码块");
        b=100;
    }
}

运行结果
在这里插入图片描述

通过数组定义类引用,和引用类的常量(不会会发生类的初始化)

package com.qcby.algorithm;

public class Test01 {
    static {
        System.out.println("main所在的类进行初始化");
    }
    public static void main(String[] args) {
       //通过数组定义类引用
        B[]b=new B[10];
        //调用静态常量
        System.out.println(B.NUMBER);
    }
}
class A{
    static int a;
    A(){
        System.out.println("父类执行构造函数");
    }
    {
        System.out.println("父类执行代码块");
    }
    static {
        System.out.println("父类执行静态代码块");
        a=10;
    }
    public static void study(){
        System.out.println("好好学习!");
    }
}
class B extends A{
    static final int NUMBER=666;
    int b=100;
    B(){
        System.out.println("子类执行构造函数");
    }
    {
        System.out.println("子类执行代码块");
    }
    static {
        System.out.println("子类执行静态代码块");
    }
}

运行结果:
在这里插入图片描述
有什么问题希望小伙伴们在评论区积极留言~
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值