类的加载、连接、初始化

类的生命周期

类的加载、连接、初始化

  在Java代码中,类型的加载、连接与初始化过程都是在程序运行期间完成的,提供了更大的灵活性,增加了更多的可能性。

加载:查找并加载类的二进制数据

连接

      验证:确保加载的类的正确性

      准备:为类的静态变量分配内存,并将其初始化为默认值

      解析:将Java中的符号应用转化为直接引用

初始化:为类的静态变量赋予正确的初始值

类加载

  类加载器ClassLoader将java的.class文件中的二进制数据读入到内存中,将其放在运行时数据区的方法区中加载后,虚拟机在堆区创建一个与该类对应java.lang.Class对象,不管类的对象有多少个,与此类对应的Class对象只有一个,Class对象用来封装类在方法区内的数据结构,所以类里面的内容都可以通过Class对象获取。Class对象是反射的入口。类的加载并不是你首次使用的时候去加载,而是预料到某个类要被使用的时候预先加载它,加载过程中不会报错,只有在程序首次主动使用时,才会报错。

类主动使用

  类的主动使用,将造成类的初始化,主动使用主要包括以下七类,其余使用均为被动使用:

  1、new

  2、调用或者设置静态变量

  3、调用静态方法

  4、有main方法的类

  5、初始化子类时,先初始化父类

  6、反射

  7、JDK1.7开始提供的动态语言支持,java.lang.invoke.MethodHandle实例的解析结果,REF_getStatic,REF_putStatic,REF_invokeStatic句柄对应的类没有初始化则初始化。

 

注意:

  1、对于静态字段来说,只有直接定义了该字段的类才会被初始化,当一个类在初始化时,要求其父类都已经初始化完毕。

  2、常量在编译阶段会存入到调用这个常量的方法所在的类的常量池中,本质上调用类并没有直接引用到定义常量的类,不会造成初始化

  3、当常量值并非在编译期间可以确定的,那么其值就不会被放到调用类的常量池中,这是会导致主动使用,造成初始化

  4、对于数组实例来说,其类型是由JVM运行期动态生成的,其父类型就是Object,不会造成数组元素类初始化

  5、当接口在初始化时,并不要求父接口都完成初始化;只有真正使用到父接口时,才会初始化

package com.jvm;

/**
 * -XX:+TraceClassLoading 监听加载了哪些类,
 * TraceClassLoading前的+号表示开启某个功能;-号表示关闭某个功能
 * -XX:<option>=<option> 表示为某个参数赋值
 */
public class Test1 {
    static {
        System.out.println("main static block");
    }
    public static void main(String[] args) throws Exception {
        //new,造成类初始化
        new newTest();
        System.out.println("====================");
        //反射造成类初始化
        Class cls = Class.forName("com.jvm.ReflectTest");
        System.out.println("====================");
        //直接调用父类静态变量不会初始化子类
        System.out.println(Child1.str);
        System.out.println("====================");
        //调用子类的静态变量,将先初始化父类(接口除外),然后初始化自己
        System.out.println(Child2.str2);
        System.out.println("====================");
        //调用确定初始值的常量,不是主动使用,不会造成初始化
        System.out.println(Child3.str2);
        System.out.println("====================");
        //调用不确定初始值的常量,会造成初始化
        System.out.println(Child4.str2);
        System.out.println("====================");
        //接口不会被初始化
        System.out.println(Child5.str);
        System.out.println("==========================");
        //初始化将按照静态变量顺序执行
        System.out.println(Singleton.a);
        System.out.println(Singleton.b);

    }
}
class newTest{
    static {
        System.out.println("newTest static block");
    }
}
class ReflectTest{
    static {
        System.out.println("ReflectTest static block");
    }
}
class Parent1{
    public static String str = "parent";
    static {
        System.out.println("parent1 static block");
    }
}
class Child1 extends Parent1{
    public static String str2 = "child";
    static {
        System.out.println("child1 static block");
    }
}
class Parent2{
    public static String str = "parent";
    static {
        System.out.println("parent2 static block");
    }
}
class Child2 extends Parent2{
    public static String str2 = "child";
    static {
        System.out.println("child2 static block");
    }
}

class Parent3{
    public static String str = "parent";
    static {
        System.out.println("parent3 static block");
    }
}
class Child3 extends Parent3{
    public static final String str2 = "child";
    static {
        System.out.println("child3 static block");
    }
}
class Parent4{
    public static String str = "parent";
    static {
        System.out.println("parent4 static block");
    }
}
class Child4 extends Parent4{
    public static final double str2 = Math.random();
    static {
        System.out.println("Child4 static block");
    }
}
interface Parent5{
    public static Thread thread = new Thread(){
        {
            System.out.println("haha");
        }
    };
}
class Child5 implements Parent5{
    public static String str = "parent";
    static {
        System.out.println("Child5 static block");
    }
}

class Singleton{
    public static int a ;
    private static Singleton instentce = new Singleton();
    public static int b = 0;
    private Singleton() {
        a++;
        b++;
    }
    public static Singleton getInstentce(){
        return instentce;
    }
}

执行main得到如下结果:

main static block
newTest static block
====================
ReflectTest static block
====================
parent1 static block
parent
====================
parent2 static block
child2 static block
child
====================
child
====================
parent4 static block
Child4 static block
0.17572662368886327
====================
Child5 static block
parent
==========================
1
0

posted @ 2020-05-06 16:08  慢跑  阅读(245)  评论(0编辑  收藏  举报