Java:<init>と<clinit>の違いは何ですか?


93

次のテキストを理解できません...それ<clinit>は空のコンストラクターのためのものですか?2つの異なるバージョンを持つことが重要なのはなぜですか?

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)を引き継ぎます。

クラスまたはインターフェースは最大で1つのクラスまたはインターフェース初期化メソッドを持ち、そのメソッドを呼び出すことによって初期化されます(§2.17.4)。クラスまたはインターフェースの初期化メソッドは静的であり、引数を取りません。それは特別な名前を持ってい<clinit>ます。この名前はコンパイラによって提供されます。名前<clinit>は有効な識別子ではないため、Javaプログラミング言語で作成されたプログラムで直接使用することはできません。クラスおよびインターフェースの初期化メソッドは、Java仮想マシンによって暗黙的に呼び出されます。Java仮想マシンのinw2structionから直接呼び出されることはありませんが、クラス初期化プロセスの一部として間接的にのみ呼び出されます。

回答:


141

<init> インスタンスの(またはいずれかの)コンストラクタであり、非静的フィールドの初期化です。

<clinit> クラスの静的初期化ブロックと静的フィールド初期化です。

class X {

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

   private int x = 1;   // <init>

   X(){
      // <init>
   }

   static {
      // <clinit>
   }

}


14
私の推測は「クラス」です。
Thilo、2015

2
@Thilo興味深いのは、JVMがクラス定義をさらに別のタイプのオブジェクトとしても扱うためです。
ジョナサンノイフェルド2015

@JonathanNeufeld正しいですが、いくつかの特別なルールがあると思います。(クラス初期化子によって呼び出される)このメソッドは、ネイティブ...としてマークされているgrepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/...
ケイドダニエル

@Thiloは「ClassLoader」を表すこともできます。
Duncan Calvert


13

<init>とは、<clinit>それがある<init>のに対し、オブジェクトのインスタンスを初期化するコンストラクタメソッドに使用される<clinit>クラスオブジェクト自体を初期化するために使用されます。たとえば、staticクラスレベルのフィールドの初期化は<clinit>、クラスが読み込まれて初期化されるときに行われます。


1

追加するだけです。Class.forNameメソッドを使用する場合、クラスを初期化するだけです。したがって、このメソッド内からはclin​​itのみが呼び出され、forNameから返されたオブジェクトでnewInstanceを使用すると、インスタンスの初期化のためにinitが呼び出されます。以下のコードを使用して、デバッグで確認できます。

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

テストするには、

   Class<ByteCodeParent> bcp2 =(Class<ByteCodeParent>) Class.forName("ByteCodeParent");
ByteCodeParent bcp4= bcp2.newInstance();
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.