Java: Apa perbedaan antara <init> dan <clinit>?

95

Saya tidak dapat memahami teks berikut ... Apakah itu berarti <clinit>untuk konstruktor kosong? Mengapa penting untuk memiliki dua versi berbeda?

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

2.9. Special Methods

Pada level mesin virtual Java, setiap konstruktor (§2.12) muncul sebagai metode inisialisasi instance yang memiliki nama khusus <init>. Nama ini disediakan oleh kompiler. Karena nama <init>bukan pengidentifikasi yang valid, nama tidak dapat digunakan secara langsung dalam program yang ditulis dalam bahasa pemrograman Java. Metode inisialisasi instance dapat dipanggil hanya dalam mesin virtual Java oleh instruksi khusus pemanggilan, dan metode tersebut dapat dipanggil hanya pada instance kelas yang tidak diinisialisasi. Metode inisialisasi instance mengambil izin akses (§2.7.4) dari konstruktor tempat asalnya.

Sebuah kelas atau antarmuka memiliki paling banyak satu kelas atau metode inisialisasi antarmuka dan diinisialisasi (§2.17.4) dengan menjalankan metode itu. Metode inisialisasi kelas atau antarmuka bersifat statis dan tidak memerlukan argumen. Itu memiliki nama khusus <clinit>. Nama ini disediakan oleh kompiler. Karena nama <clinit>bukan pengenal yang valid, nama tidak dapat digunakan secara langsung dalam program yang ditulis dalam bahasa pemrograman Java. Metode inisialisasi kelas dan antarmuka dipanggil secara implisit oleh mesin virtual Java; mereka tidak pernah dipanggil secara langsung dari instruksi mesin virtual Java, tetapi dipanggil hanya secara tidak langsung sebagai bagian dari proses inisialisasi kelas.

Jayan
sumber

Jawaban:

143

<init> adalah (atau salah satu) konstruktor untuk instance, dan inisialisasi bidang non-statis.

<clinit> adalah blok inisialisasi statis untuk kelas, dan inisialisasi bidang statis.

class X {

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

   private int x = 1;   // <init>

   X(){
      // <init>
   }

   static {
      // <clinit>
   }

}
Thilo
sumber
5
Untuk apa CLberdiri?
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
14
Tebakan saya adalah "kelas".
Thilo
2
@Thilo itu menarik karena JVM memperlakukan definisi kelas hanya sebagai tipe objek lain juga.
Jonathan Neufeld
@JonathanNeufeld benar, meskipun menurut saya ada beberapa aturan khusus. Metode ini (dipanggil oleh penginisialisasi kelas) ditandai sebagai asli ... grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/…
Cade Daniel
@Thilo itu juga bisa berarti "ClassLoader".
Duncan Calvert
13

Perbedaan antara <init>and <clinit>is yang <init>digunakan untuk metode konstruktor yang menginisialisasi sebuah instance objek, sedangkan <clinit>digunakan untuk menginisialisasi objek kelas itu sendiri. Misalnya, inisialisasi setiap staticbidang tingkat kelas dilakukan <clinit>saat kelas dimuat dan diinisialisasi.

rsp
sumber
1

Hanya untuk menambahkan Jika Anda menggunakan metode Class.forName, itu hanya menginisialisasi kelas. Jadi dari dalam metode ini, itu membuat panggilan hanya ke klinit dan ketika Anda menggunakan newInstance pada objek yang dikembalikan dari forName, itu akan memanggil init untuk inisialisasi instance. Anda dapat menggunakan kode di bawah ini untuk melihatnya di debug.

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

Untuk menguji, gunakan

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