Java:<init>和<clinit>有什么区别?

我无法理解下面的文本…是否意味着<clinit>是空的构造函数? 为什么重要的是有两个不同的版本?

https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-2.html

 2.9. Special Methods 

在Java虚拟机的层面上,每个构造函数(§2.12)都作为一个具有特殊名称<init>的实例初始化方法出现。 这个名字是由编译器提供的。 由于名称<init>不是有效的标识符,因此不能直接在用Java编程语言编写的程序中使用。 实例初始化方法只能在invokespecial指令的Java虚拟机中调用,并且只能在未初始化的类实例上调用它们。 一个实例初始化方法承担了派生它的构造函数的访问权限(第2.7.4节)。

一个类或接口至多有一个类或接口的初始化方法,并通过调用该方法初始化(§2.17.4)。 类或接口的初始化方法是静态的,不需要参数。 它有一个特殊的名字<clinit> 。 这个名字是由编译器提供的。 由于名称<clinit>不是有效的标识符,因此不能直接在用Java编程语言编写的程序中使用。 类和接口初始化方法由Java虚拟机隐式调用; 它们不会直接从任何Java虚拟机inw2tru中调用,而只是间接作为类初始化过程的一部分被调用。

<init>是实例的(或其中一个)构造函数,以及非静态的字段初始化。

<clinit>是类的静态初始化块,以及静态字段初始化。

 class X { static Log log = LogFactory.getLog(); // <clinit> private int x = 1; // <init> X(){ // <init> } static { // <clinit> } } 

<init>表示构造函数, <clinit>表示静态初始化程序 : Java教程中的“Static Initialization Blocks”,Java中的 静态初始化程序 。

<init><clinit>之间的区别在于<init>用于初始化对象实例的构造函数方法,而<clinit>用于初始化类对象本身。 例如初始化任何static类级别的字段是在<clinit>完成的,当类被加载和initalised。

只需添加如果您使用Class.forName方法,它只会初始化类。 所以从这个方法中,它只会调用clinit,并且在从forName返回的对象上使用newInstance时,它将调用init来进行实例初始化。 您可以使用下面的代码在debugging中看到它。

 public class ByteCodeParent { public static String name="ByteCode"; public ByteCodeParent() { System.out.println("In Constructor"); } static { System.out.println("In Static"); } { System.out.println("In Instance"); } 

要testing,使用

  Class<ByteCodeParent> bcp2 =(Class<ByteCodeParent>) Class.forName("ByteCodeParent"); ByteCodeParent bcp4= bcp2.newInstance();