java类的初始化结论二

结论:
1.JVM 参数:-XX:+TraceClassLoading  输出类的加载信息


2. 类初始化时会加载其实现的接口,不会初始化其实现的接口


3. 接口中如果是常量且该常量值为字面量时,不会加载其接口本身和其父接口,故也不会进行初始化;其中原因是在编译过程中如果常量是字面量会被编译器将常量值直接放入调用类的静态池中     


4. 接口中如果是常量且该常量值为不为字面量时,会加载其接口本身和其父接口,会初始化接口本身,不会初始化其父接口


5. 上述结论中提到的字面量是指: 类或接口被 static final 修辞的属性的值是在代码编译期间就能确定其具体的值是什么,比如:数值 8 ,字符串"A",而不能确定其值,只能是在代码运行时,才能道其具体的值,就是非字面量。

 

6. 当子类引用父类的静态变量和静态方法时,如果子类没有重写该静态变量和静态方法,那么程序在执行的时候是不会导致子类的初始化的。



小技巧: 巧用代码块,来确定一个对象是否被实例化,而不仅仅靠构造方法,还可以利用代码块来验证

import java.util.Date;
import java.util.Random;

/**
 * 小知识点:
 *  1.JVM 参数:-XX:+TraceClassLoading  输出类的加载信息
 *  2. 类初始化时会加载其实现的接口,不会初始化其实现的接口
 *  3. 接口中如果是常量且该常量值为字面量时,不会加载其接口本身和其父接口,故也不会进行初始化;其中原因是在编译过程中如果常量是字面量会被编译器将常量值直接放入调用类的静态池中
 *  4. 接口中如果是常量且该常量值为不为字面量时,会加载其接口本身和其父接口,会初始化接口本身,不会初始化其父接口
 *  5. 上述结论中提到的字面量是指: 类或接口被 static final 修辞的属性的值是在代码编译期间就能确定其具体的值是什么,比如:数值 8 ,字符串"A",而不能确定其值,只能是在代码运行时,才能
 *      知道其具体的值,就是非字面量。
 *  小技巧:
 *      1. 巧用代码块,来确定一个对象是否被实例化,而不仅仅靠构造方法,还可以利用代码块来验证
 */
public class Test3 {

    public static void main(String[] args) {

//        Child3 child3 = new Child3(); //类初始化时会加载其实现的接口,不会初始化其实现的接口
//        System.out.println(IChild3.b);//接口中如果是常量且该常量值为字面量时,不会加载其接口本身和其父接口,故也不会进行初始化;其中原因是在编译过程中如果常量是字面量会被编译器将常量值直接放入调用类的静态池中
//        System.out.println(IChild3.bb);//接口中如果是常量且该常量值为不为字面量时,会加载其接口本身和其父接口,会初始化接口本身,不会初始化其父接口

        System.out.println(IChild3.bbbb);//除了利用构造方法来确认是否创建了类的实例对象,还可以用代码块进行验证类实例是否创建

    }

}

interface IParent3 {

    int a = 10;

    /**
     * 用于验证接口是否初始化
     */
    Date aa = new Date(){

        {
            System.out.println("IParent3 init !");
        }
    };

}

interface IChild3 extends IParent3 {
//    int b = 6;

//    int bb = new Random().nextInt(20);

    /**
     * 用于验证接口是否初始化,原因是:当类或接口在初始化时,会从上至下初始化静态属性,并赋初始值,而在赋初始值时,
     * 就会创建对象,从而在创建对象时,会执行其代码块,从而得出当前接口是否执行了初始化操作
     */
    Date bbb = new Date(){

        {
            System.out.println("IChild init !");
        }
    };

    Child3_3 bbbb = new Child3_3();

}

class Child3 implements IParent3 {
    public static int c = 20;
    //类初始化时,会执行static 代码块
    static {
        System.out.println("Child3 init");
    }

}

class Child3_3 {

    public Child3_3() {
        System.out.println("Child3_3 was created ");
    }

    {
        System.out.println("Child3_3 code block invoke");
    }

}
/**
 * 6. 当子类引用父类的静态变量和静态方法时,如果子类没有重写该静态变量和静态方法,那么程序在执行的时候是不会导致子类的初始化的。
 */
public class Test4 {

    public static void main(String[] args) {
        System.out.println(Child4.a);
        System.out.println("---------------------");
        Child4.doSomething();
        System.out.println("------------------");
        System.out.println(Child4.b);
    }

}

class Parent4 {

    public static int a = 5;

    public static int b = 6;

    static {
        System.out.println("Parent4 init");
    }

    public static void doSomething() {
        System.out.println("do somethings .....");
    }

}

class Child4 extends Parent4{

    public static int b = 16;

    static {
        System.out.println("Child init");
    }

}


 

发布了54 篇原创文章 · 获赞 31 · 访问量 8万+

猜你喜欢

转载自blog.csdn.net/u012149894/article/details/104828722