Java: Was ist der Unterschied zwischen <init> und <clinit>?

93

Ich kann den folgenden Text nicht verstehen ... Bedeutet das, dass <clinit>es sich um leere Konstruktoren handelt? Warum ist es wichtig, zwei verschiedene Versionen zu haben?

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

2.9. Special Methods

Auf der Ebene der Java Virtual Machine wird jeder Konstruktor (§2.12) als Instanzinitialisierungsmethode mit dem speziellen Namen angezeigt <init>. Dieser Name wird von einem Compiler bereitgestellt. Da der Name <init>kein gültiger Bezeichner ist, kann er nicht direkt in einem Programm verwendet werden, das in der Programmiersprache Java geschrieben ist. Instanzinitialisierungsmethoden können nur innerhalb der Java Virtual Machine durch die Anweisung invokespecial aufgerufen werden, und sie können nur für nicht initialisierte Klasseninstanzen aufgerufen werden. Eine Instanzinitialisierungsmethode übernimmt die Zugriffsberechtigungen (§2.7.4) des Konstruktors, von dem sie abgeleitet wurde.

Eine Klasse oder Schnittstelle hat höchstens eine Klassen- oder Schnittstelleninitialisierungsmethode und wird durch Aufrufen dieser Methode initialisiert (§2.17.4). Die Initialisierungsmethode einer Klasse oder Schnittstelle ist statisch und akzeptiert keine Argumente. Es hat den besonderen Namen <clinit>. Dieser Name wird von einem Compiler bereitgestellt. Da der Name <clinit>kein gültiger Bezeichner ist, kann er nicht direkt in einem Programm verwendet werden, das in der Programmiersprache Java geschrieben ist. Klassen- und Schnittstelleninitialisierungsmethoden werden implizit von der Java Virtual Machine aufgerufen. Sie werden niemals direkt von einer Java Virtual Machine inw2struction aufgerufen, sondern nur indirekt als Teil des Klasseninitialisierungsprozesses.

Jayan
quelle

Antworten:

141

<init> ist der (oder einer der) Konstruktor (e) für die Instanz und die nicht statische Feldinitialisierung.

<clinit> sind die statischen Initialisierungsblöcke für die Klasse und die statische Feldinitialisierung.

class X {

   static Log log = LogFactory.getLog(); // <clinit>

   private int x = 1;   // <init>

   X(){
      // <init>
   }

   static {
      // <clinit>
   }

}
Thilo
quelle
5
Wofür steht CL?
Ciro Santilli 法轮功 冠状 病. 事件 法轮功
14
Meine Vermutung ist "Klasse".
Thilo
2
@Thilo, das ist interessant, weil die JVM eine Klassendefinition auch als einen weiteren Objekttyp behandelt.
Jonathan Neufeld
@ JonathanNeufeld wahr, obwohl ich denke, dass es einige spezielle Regeln gibt. Diese Methode (vom Klasseninitialisierer aufgerufen) wird als native markiert ... grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/…
Cade Daniel
@Thilo könnte es auch für "ClassLoader" stehen.
Duncan Calvert
13

Der Unterschied zwischen <init>und <clinit>besteht darin, dass <init>Konstruktormethoden verwendet werden, die eine Objektinstanz initialisieren, während <clinit>das Klassenobjekt selbst initialisiert wird. Zum Beispiel erfolgt die Initialisierung von staticFeldern auf <clinit>Klassenebene, wenn die Klasse geladen und initialisiert wird.

rsp
quelle
1

Nur zum Hinzufügen Wenn Sie die Class.forName-Methode verwenden, wird nur die Klasse initialisiert. Innerhalb dieser Methode wird nur klinit aufgerufen. Wenn Sie newInstance für das von forName zurückgegebene Objekt verwenden, wird init für die Instanzinitialisierung aufgerufen. Sie können den folgenden Code verwenden, um ihn im Debug anzuzeigen.

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");
 }

Verwenden Sie zum Testen

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