• <clinit>() 和 <init>()


    原文:https://www.cnblogs.com/aspirant/p/7200523.html

    <clinit>() 类构造器方法

      在 类初始化阶段 被执行

      由编译器自动收集类中的所有类变量的赋值动作和静态语句块static{}中的语句合并产生的,编译器收集的顺序是由语句在源文件中出现的顺序所决定的,静态语句块只能访问到定义在静态语句块之前的变量,定义在它之后的变量,在前面的静态语句块可以赋值,但是不能访问。

    只能是顺序执行

      <clinit>()它不需要显示地调用父类构造器,虚拟机会保证在子类<clinit>()方法执行之前,父类的<clinit>()方法方法已经执行完毕

      接口中不能使用静态语句块,但仍然有变量初始化的赋值操作,因此接口与类一样都会生成<clinit>()方法。但接口与类不同的是,执行接口的<clinit>()方法不需要先执行父接口的<clinit>()方法。只有当父接口中定义的变量使用时,父接口才会初始化。另外,接口的实现类在初始化时也一样不会执行接口的<clinit>()方法。

      虚拟机会保证一个类的<clinit>()方法在多线程环境中被正确的加锁、同步,如果多个线程同时去初始化一个类,那么只会有一个线程去执行这个类的<clinit>()方法,其他线程都需要阻塞等待,直到活动线程执行<clinit>()方法完毕。如果在一个类的<clinit>()方法中有耗时很长的操作,就可能造成多个线程阻塞,在实际应用中这种阻塞往往是隐藏的。

      <clinit>()方法对于类或者接口来说并不是必需的,如果一个类中没有静态语句块,也没有对变量的赋值操作,那么编译器可以不为这个类生产<clinit>()方法。

    <init>() 实例构造器方法

      init is the (or one of the) constructor(s) for the instance, and non-static field initialization. 对非静态变量解析初始化

      在创建实例的时候会被调用, 包含:

    1. 遇到new,getstatic,putstatic,invokestatic这失调字节码指令时,如果类没有进行过初始化,则需要先触发其初始化。生成这4条指令的最常见的Java代码场景是:使用new关键字实例化对象的时候、读取或设置一个类的静态字段(被final修饰、已在编译器把结果放入常量池的静态字段除外)的时候,以及调用一个类的静态方法的时候。
    2. 使用java.lang.reflect包的方法对类进行反射调用的时候,如果类没有进行过初始化,则需要先触发其初始化。
    3. 当初始化一个类的时候,如果发现其父类还没有进行过初始化,则需要先触发其父类的初始化。
    4. 当虚拟机启动时,用户需要指定一个要执行的主类(包含main()方法的那个类),虚拟机会先初始化这个主类。
    5. 当使用jdk1.7动态语言支持时,如果一个java.lang.invoke.MethodHandle实例最后的解析结果REF_getstatic,REF_putstatic,REF_invokeStatic的方法句柄,并且这个方法句柄所对应的类没有进行初始化,则需要先出触发其初始化。
  • 相关阅读:
    牛客网2017年校招全国统一模拟笔试(第三场)编程题集合
    侯捷STL学习(六)--深入list && Iterator traits
    侯捷STL学习(五)--allocator和容器之间的实现关系
    侯捷STL学习(四)--OOP-GP/操作符重载-泛化特化
    侯捷STL学习(三)--分配器测试
    侯捷STL学习(二)--序列容器测试
    牛客网2017年校招全国统一模拟笔试(第一场)编程题集合
    数据库面试题(一)
    SQL基础理论题
    基本SQL练习题--选课经典例题
  • 原文地址:https://www.cnblogs.com/DDiamondd/p/11295339.html
Copyright © 2020-2023  润新知