Java: Jaka jest różnica między <init> a <clinit>?


94

Nie rozumiem następującego tekstu ... Czy to znaczy, że <clinit>jest dla pustych konstruktorów? Dlaczego ważne jest, aby mieć dwie różne wersje?

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

2.9. Special Methods

Na poziomie wirtualnej maszyny Javy każdy konstruktor (§2.12) pojawia się jako metoda inicjalizacji instancji o specjalnej nazwie <init>. Ta nazwa jest dostarczana przez kompilator. Ponieważ nazwa <init>nie jest poprawnym identyfikatorem, nie można jej używać bezpośrednio w programie napisanym w języku programowania Java. Metody inicjowania instancji mogą być wywoływane tylko w wirtualnej maszynie Javy za pomocą instrukcji invokespecial i mogą być wywoływane tylko w przypadku niezainicjowanych instancji klas. Metoda inicjalizacji instancji przyjmuje uprawnienia dostępu (§ 2.7.4) konstruktora, z którego została wyprowadzona.

Klasa lub interfejs ma co najwyżej jedną metodę inicjalizacji klasy lub interfejsu i jest inicjowana (§2.17.4) przez wywołanie tej metody. Metoda inicjalizacji klasy lub interfejsu jest statyczna i nie pobiera żadnych argumentów. Ma specjalną nazwę <clinit>. Ta nazwa jest dostarczana przez kompilator. Ponieważ nazwa <clinit>nie jest poprawnym identyfikatorem, nie można jej używać bezpośrednio w programie napisanym w języku programowania Java. Metody inicjowania klas i interfejsów są wywoływane niejawnie przez wirtualną maszynę języka Java; nigdy nie są wywoływane bezpośrednio z żadnej wirtualnej maszyny Javy w konstrukcji w2, ale są wywoływane tylko pośrednio w ramach procesu inicjalizacji klasy.

Odpowiedzi:


143

<init> jest konstruktorem (lub jednym z konstruktorów) instancji oraz inicjalizacją pola niestatycznego.

<clinit> to statyczne bloki inicjalizacyjne dla klasy i statyczna inicjalizacja pola.

class X {

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

   private int x = 1;   // <init>

   X(){
      // <init>
   }

   static {
      // <clinit>
   }

}


14
Domyślam się, że to „klasa”.
Thilo,

2
@Thilo to interesujące, ponieważ JVM traktuje definicję klasy jako jeszcze jeden typ obiektu.
Jonathan Neufeld,

@JonathanNeufeld prawda, chociaż myślę, że są pewne specjalne zasady. Ta metoda (wywoływana przez inicjator klasy) jest oznaczona jako natywna ... grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/
Cade Daniel

@Thilo może również oznaczać „ClassLoader”.
Duncan Calvert


13

Różnica między <init>i <clinit>polega na tym, że <init>jest używany w przypadku metod konstruktora, które inicjują wystąpienie obiektu, podczas gdy <clinit>jest używany do inicjowania samego obiektu klasy. Na przykład inicjalizacja staticpól na poziomie klasy jest wykonywana <clinit>podczas ładowania i inicjalizacji klasy.


1

Wystarczy dodać Jeśli używasz metody Class.forName, to tylko inicjalizuje ona klasę. Więc z tej metody wywołuje tylko Clinit, a gdy użyjesz newInstance na obiekcie zwróconym przez forName, wywoła init w celu zainicjowania instancji. Możesz użyć poniższego kodu, aby zobaczyć go podczas debugowania.

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

Aby przetestować, użyj

   Class<ByteCodeParent> bcp2 =(Class<ByteCodeParent>) Class.forName("ByteCodeParent");
ByteCodeParent bcp4= bcp2.newInstance();
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.