类的主动使用实战

一 实战——实例化

1 代码

package chapter03.java1;

import org.junit.Test;

import java.io.*;

/**
* 测试类的主动使用:意味着会调用类的 <clinit>(),即执行了类的初始化阶段
*
* 当创建一个类的实例时,比如使用 new 关键字,或者通过反射、克隆、反序列化。
*/
public class ActiveUse1 {
    public static void main(String[] args) {
        // 使用 new 关键字
        Order order = new Order();
    }

    // 序列化的过程:
    @Test
    public void test1() {
        ObjectOutputStream oos = null;
        try {
            oos = new ObjectOutputStream(new FileOutputStream("order.dat"));


            oos.writeObject(new Order());
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (oos != null)
                    oos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    // 反序列化的过程:(验证)
    @Test
    public void test2() {
        ObjectInputStream ois = null;
        try {
            ois = new ObjectInputStream(new FileInputStream("order.dat"));
            Order order = (Order) ois.readObject();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } finally {
            try {
                if (ois != null)
                    ois.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

class Order implements Serializable {
    static {
        System.out.println("Order类的初始化过程");
    }
}

2 测试

执行 main 方法时

Order类的初始化过程

执行 test1 时

Order类的初始化过程

执行 test2 时

Order类的初始化过程

二 实战——静态方法

1 代码

package chapter03.java1;

import org.junit.Test;

import java.io.*;

/**
* 测试类的主动使用:意味着会调用类的 <clinit>(),即执行了类的初始化阶段
*
* 当调用类的静态方法时,即当使用了字节码 invokestatic 指令。
*/
public class ActiveUse1 {
    @Test
    public void test3() {
        Order.method();
    }
}


class Order implements Serializable {
    static {
        System.out.println("Order类的初始化过程");
    }

    public static void method() {
        System.out.println("Order method()....");
    }
}

2 测试

Order类的初始化过程

Order method()....

三 实战——静态字段

1 代码

package chapter03.java1;

import org.junit.Test;

import java.util.Random;

/**
*
* 当使用类、接口的静态字段时(final修饰特殊考虑),比如,使用 getstatic 或者 putstatic 指令。(对应访问变量、赋值变量操作)
*
*/
public class ActiveUse2 {
    @Test
    public void test1(){
        //System.out.println(User.num); // test1_1:类初始化了,因为 num 是变量
        //System.out.println(User.num1); // test1_2:类没有初始化,因为 num1 是静态常量
        System.out.println(User.num2); // test1_3:类初始化了,因为 num2 不是字面量方式声明的,需要方法调用,编译期间无法确定
    }

    @Test
    public void test2(){
        //System.out.println(CompareA.NUM1); // test2_1:接口不需要初始化,因为 NUM1 是静态常量
        //System.out.println(CompareA.NUM2); // test1_2:接口需要初始化。因为 因为 NUM2 不是字面量方式声明的,而是方法调用,编译期间无法确定
    }
}

class User{
    static{
        System.out.println("User类的初始化过程");
    }

    public static int num = 1;
    public static final int num1 = 1;
    public static final int num2 = new Random().nextInt(10);


}

interface CompareA{
    public static final Thread t = new Thread(){
        {
            System.out.println("CompareA的初始化");
        }
    };

    public static final int NUM1 = 1;
    public static final int NUM2 = new Random().nextInt(10);
}

2 测试

当只运行test1_1

User类的初始化过程

1

当只运行test1_2

1

当只运行test1_3

User类的初始化过程

8

当只运行test2_1

1

当只运行test2_2

CompareA的初始化

2

四 实战——类的主动使用其它情况

1 代码

package chapter03.java1;

import org.junit.Test;

import java.util.Random;

/**
* 类的主动使用其他情况
* 8. 当初次调用 MethodHandle 实例时,初始化该 MethodHandle 指向的方法所在的类。
* (涉及解析REF_getStatic、REF_putStatic、REF_invokeStatic方法句柄对应的类)
*/
public class ActiveUse3 {
    static {
        System.out.println("ActiveUse3的初始化过程");
    }

    // 4 当使用java.lang.reflect包中的方法反射类的方法时。比如:Class.forName("com.xxxx.xxx.Test")
    @Test
    public void test1() {
        try {
            Class clazz = Class.forName("chapter03.java1.Order");
            // 输出语句
            // ActiveUse3的初始化过程
            // Order类的初始化过程
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    // 5 当初始化子类时,如果发现其父类还没有进行过初始化,则需要先触发其父类的初始化。
    // 注意:
    // 当 Java 虚拟机初始化一个类时,要求它的所有父类都已经被初始化,但是这条规则并不适用于接口。
    // >在初始化一个类时,并不会先初始化它所实现的接口
    // >在初始化一个接口时,并不会先初始化它的父接口
    // 因此,一个父接口并不会因为它的子接口或者实现类的初始化而初始化。只有当程序首次使用特定接口的静态字段时,
    // 才会导致该接口的初始化。
    @Test
    public void test2() {
        System.out.println(Son.num);// 接口 CompareD 不会初始化
        // 依次输出
        // ActiveUse3的初始化过程
        // Father类的初始化过程
        // Son类的初始化过程
        // 1
    }

    @Test
    public void test3() {
        System.out.println(CompareC.NUM1); // CompareC 父接口 CompareB 并不会初始化
        // 依次输出
        // ActiveUse3的初始化过程
        // CompareC的初始化  --> 子接口初始化了,但是父接口并没有初始化
        // 2094196067
    }

    // 6 如果一个接口定义了 default 方法,那么直接实现或者间接实现该接口的类的初始化,该接口要在其之前被初始化。
    // 如果 Son2 还有子类,根据5,那么其子类的父类,父类的父类也都要被初始化
    @Test
    public void test4() {
        System.out.println(Son2.num);
        // 依次输出
        // ActiveUse3的初始化过程
        // Father类的初始化过程
        // CompareB的初始化 -> CompareB接口定义了default方法,所以接口要初始化,注意区分与CompareD的区别
        // Son2类的初始化过程
        // 1
    }

    // 7 当虚拟机启动时,用户需要指定一个要执行的主类(包含main()方法的那个类),虚拟机会先初始化这个主类。
    public static void main(String[] args) {
        System.out.println("hello");
        // 依次输出
        // ActiveUse3的初始化过程
        // hello
    }
}

class Father {
    static {
        System.out.println("Father类的初始化过程");
    }
}

class Son extends Father implements CompareD {
    static {
        System.out.println("Son类的初始化过程");
    }


    public static int num = 1;
}

class Son2 extends Father implements CompareB {
    static {
        System.out.println("Son2类的初始化过程");
    }


    public static int num = 1;
}

interface CompareB {
    public static final Thread t = new Thread() {
        {
            System.out.println("CompareB的初始化");
        }
    };

    public default void method1() {
        System.out.println("你好!");
    }
}

interface CompareC extends CompareB {
    public static final Thread t = new Thread() {
        {
            System.out.println("CompareC的初始化");
        }
    };

    public static final int NUM1 = new Random().nextInt();
}

interface CompareD {
    public static final Thread t = new Thread() {
        {
            System.out.println("CompareD的初始化");
        }
    };
}

2 测试

当执行 test1 时

ActiveUse3的初始化过程

Order类的初始化过程

当执行 test2 时

ActiveUse3的初始化过程

Father类的初始化过程

Son类的初始化过程

1

当执行 test3 时

ActiveUse3的初始化过程

CompareC的初始化

96077485

当执行 test4 时

ActiveUse3的初始化过程

Father类的初始化过程

CompareB的初始化

Son2类的初始化过程

1

当执行 main 时

ActiveUse3的初始化过程

hello

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值