Java: <init> ve <clinit> arasındaki fark nedir?


95

Aşağıdaki metni anlayamıyorum ... Bunun <clinit>boş kurucular için olduğu anlamına mı geliyor ? İki farklı versiyona sahip olmak neden önemlidir?

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

2.9. Special Methods

Java sanal makinesi düzeyinde, her kurucu (§2.12), özel ada sahip bir örnek başlatma yöntemi olarak görünür <init>. Bu isim bir derleyici tarafından sağlanır. Ad <init>, geçerli bir tanımlayıcı olmadığından, doğrudan Java programlama dilinde yazılmış bir programda kullanılamaz. Örnek başlatma yöntemleri, yalnızca Java sanal makinesinde özel olarak çağırma talimatı ile çağrılabilir ve yalnızca başlatılmamış sınıf örneklerinde çağrılabilir. Bir örnek başlatma yöntemi, türetildiği kurucunun erişim izinlerini (§2.7.4) alır.

Bir sınıf veya arabirim en fazla bir sınıfa veya arabirim başlatma yöntemine sahiptir ve bu yöntemi çağırarak başlatılır (§2.17.4). Bir sınıfın veya arabirimin başlatma yöntemi statiktir ve hiçbir argüman almaz. Özel bir adı var <clinit>. Bu ad bir derleyici tarafından sağlanır. Ad <clinit>, geçerli bir tanımlayıcı olmadığından, doğrudan Java programlama dilinde yazılmış bir programda kullanılamaz. Sınıf ve arayüz başlatma yöntemleri, Java sanal makinesi tarafından dolaylı olarak çağrılır; hiçbir zaman doğrudan herhangi bir Java sanal makine inw2struction'dan çağrılmazlar, ancak sınıf başlatma işleminin bir parçası olarak yalnızca dolaylı olarak çağrılırlar.

Yanıtlar:


144

<init> örnek için yapıcı (lar) ve statik olmayan alan başlatma (veya biridir).

<clinit> sınıf için statik başlatma blokları ve statik alan başlatmadır.

class X {

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

   private int x = 1;   // <init>

   X(){
      // <init>
   }

   static {
      // <clinit>
   }

}


14
Benim tahminim "sınıf".
Thilo

2
@Thilo bu ilginç çünkü JVM bir sınıf tanımını sadece başka bir nesne türü olarak ele alıyor.
Jonathan Neufeld

@JonathanNeufeld doğru, yine de bazı özel kurallar olduğunu düşünüyorum. Bu yöntem (sınıf başlatıcı tarafından çağrılır) yerel olarak işaretlenmiştir ... grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/…
Cade Daniel

@Thilo aynı zamanda "ClassLoader" anlamına da gelebilir.
Duncan Calvert


13

Arasındaki fark <init>ve <clinit>olduğunu <init>, oysa bir nesne örneği initialize yapıcı yöntemleri için kullanılır <clinit>sınıf nesnesi kendisi başlatmak için kullanılır. Örneğin, herhangi bir staticsınıf düzeyindeki alanın ilklendirilmesi <clinit>, sınıf yüklendiğinde ve başlatıldığında yapılır.


1

Sadece eklemek için Class.forName yöntemini kullanıyorsanız, yalnızca sınıfı başlatır. Dolayısıyla, bu yöntemin içinden, yalnızca Clinit'e bir çağrı yapar ve forName'den dönen nesnede newInstance'ı kullandığınızda, örnek başlatma için init'i çağırır. Hata ayıklamada görmek için aşağıdaki kodu kullanabilirsiniz.

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

Test etmek için kullanın

   Class<ByteCodeParent> bcp2 =(Class<ByteCodeParent>) Class.forName("ByteCodeParent");
ByteCodeParent bcp4= bcp2.newInstance();
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.