Java: Quelle est la différence entre <init> et <clinit>?


94

Je suis incapable de comprendre le texte suivant ... Cela signifie-t-il que <clinit>c'est pour les constructeurs vides? Pourquoi est-il important d'avoir deux versions différentes?

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

2.9. Special Methods

Au niveau de la machine virtuelle Java, chaque constructeur (§2.12) apparaît comme une méthode d'initialisation d'instance portant le nom spécial <init>. Ce nom est fourni par un compilateur. Comme le nom <init>n'est pas un identifiant valide, il ne peut pas être utilisé directement dans un programme écrit dans le langage de programmation Java. Les méthodes d'initialisation d'instance ne peuvent être appelées que dans la machine virtuelle Java par l'instruction invokespecial, et elles ne peuvent être appelées que sur des instances de classe non initialisées. Une méthode d'initialisation d'instance prend les droits d'accès (§2.7.4) du constructeur dont elle est dérivée.

Une classe ou une interface a au plus une méthode d'initialisation de classe ou d'interface et est initialisée (§2.17.4) en invoquant cette méthode. La méthode d'initialisation d'une classe ou d'une interface est statique et ne prend aucun argument. Il a le nom spécial <clinit>. Ce nom est fourni par un compilateur. Comme le nom <clinit>n'est pas un identifiant valide, il ne peut pas être utilisé directement dans un programme écrit dans le langage de programmation Java. Les méthodes d'initialisation de classe et d'interface sont appelées implicitement par la machine virtuelle Java; ils ne sont jamais appelés directement à partir d'une machine virtuelle Java dansw2struction, mais ne sont invoqués qu'indirectement dans le cadre du processus d'initialisation de classe.

Réponses:


142

<init> est le (ou l'un des) constructeur (s) de l'instance et l'initialisation de champ non statique.

<clinit> sont les blocs d'initialisation statique pour la classe et l'initialisation de champ statique.

class X {

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

   private int x = 1;   // <init>

   X(){
      // <init>
   }

   static {
      // <clinit>
   }

}


14
Ma conjecture est "classe".
Thilo

2
@Thilo c'est intéressant car la JVM traite une définition de classe comme un autre type d'objet.
Jonathan Neufeld

@JonathanNeufeld est vrai, même si je pense qu'il y a des règles spéciales. Cette méthode (appelée par l'initialiseur de classe) est marquée comme native ... grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/…
Cade Daniel

@Thilo cela pourrait aussi signifier "ClassLoader".
Duncan Calvert


13

La différence entre <init>et <clinit>est qu'elle <init>est utilisée pour les méthodes de constructeur qui initialisent une instance d'objet, alors qu'elle <clinit>est utilisée pour initialiser l'objet de classe lui-même. Par exemple, l'initialisation de tous staticles champs de niveau de classe est effectuée <clinit>lorsque la classe est chargée et initialisée.


1

Juste pour ajouter Si vous utilisez la méthode Class.forName, elle initialise uniquement la classe. Donc, à partir de cette méthode, il n'appelle que clinit et lorsque vous utilisez newInstance sur l'objet retourné par forName, il appellera init pour l'initialisation de l'instance. Vous pouvez utiliser le code ci-dessous pour le voir dans le débogage.

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

Pour tester, utilisez

   Class<ByteCodeParent> bcp2 =(Class<ByteCodeParent>) Class.forName("ByteCodeParent");
ByteCodeParent bcp4= bcp2.newInstance();
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.