जावा: <init> और <clinit> के बीच क्या अंतर है?


93

मैं निम्नलिखित पाठ को समझने में असमर्थ हूं ... क्या इसका मतलब यह है कि <clinit>खाली निर्माणकर्ताओं के लिए है? दो अलग-अलग संस्करण क्यों महत्वपूर्ण हैं?

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

2.9. Special Methods

जावा वर्चुअल मशीन के स्तर पर, प्रत्येक कंस्ट्रक्टर (.122.12) एक उदाहरण आरंभीकरण विधि के रूप में प्रकट होता है जिसमें विशेष नाम होता है <init>। यह नाम एक संकलक द्वारा आपूर्ति की जाती है। क्योंकि नाम <init>एक मान्य पहचानकर्ता नहीं है, इसका उपयोग सीधे जावा प्रोग्रामिंग भाषा में लिखे गए प्रोग्राम में नहीं किया जा सकता है। इंस्टेंसेस आरंभीकरण के तरीकों को केवल इनवोकेशनल इंस्ट्रक्शन द्वारा जावा वर्चुअल मशीन के भीतर लगाया जा सकता है, और उन्हें केवल अनइंस्टाल्ड क्लास इंस्टेंसेस पर ही इनवाइट किया जा सकता है। एक इंस्टेंस इनिशियलाइज़ेशन विधि कंस्ट्रक्टर की एक्सेस अनुमतियों (.72.7.4) पर ले जाती है, जहाँ से इसे प्राप्त किया गया था।

एक क्लास या इंटरफ़ेस में एक ही क्लास या इंटरफ़ेस इनिशियलाइज़ेशन मेथड होता है और उस तरीके को लागू करके इनिशियलाइज़ किया जाता है (.12.17.4)। किसी वर्ग या इंटरफ़ेस की प्रारंभिक विधि स्थिर है और कोई तर्क नहीं लेता है। इसका विशेष नाम है <clinit>। यह नाम एक संकलक द्वारा आपूर्ति की जाती है। क्योंकि नाम <clinit>एक मान्य पहचानकर्ता नहीं है, इसका उपयोग सीधे जावा प्रोग्रामिंग भाषा में लिखे गए प्रोग्राम में नहीं किया जा सकता है। क्लास और इंटरफ़ेस इनिशियलाइज़ेशन के तरीकों को जावा वर्चुअल मशीन द्वारा स्पष्ट रूप से लागू किया जाता है; वे कभी भी किसी जावा वर्चुअल मशीन इनवाइटिशन से सीधे नहीं मंगवाए जाते हैं, बल्कि इनडायरेक्टली इन क्लास इनिशियलाइज़ेशन प्रोसेस के हिस्से के तौर पर ही इनवाइट किए जाते हैं।

जवाबों:


141

<init> उदाहरण के लिए कंस्ट्रक्टर (या) में से एक है, और गैर-स्थैतिक क्षेत्र आरंभीकरण है।

<clinit> वर्ग के लिए स्थैतिक आरंभीकरण ब्लॉक हैं, और स्थैतिक क्षेत्र आरंभीकरण।

class X {

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

   private int x = 1;   // <init>

   X(){
      // <init>
   }

   static {
      // <clinit>
   }

}


14
मेरा अनुमान "वर्ग" है।
थिलो

2
@ थिलियो दिलचस्प है क्योंकि जेवीएम एक वर्ग परिभाषा को सिर्फ एक अन्य प्रकार की वस्तु भी मानता है।
जोनाथन नेफेल्ड

@JonathanNeufeld सच, हालांकि मुझे लगता है कि कुछ विशेष नियम हैं। इस विधि (जिसे क्लास इनिशियलाइज़र द्वारा कहा जाता है) को मूल के रूप में चिह्नित किया जाता है ... grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/…
Cade Daniel

@ थिलो यह "क्लासऑलडर" के लिए भी खड़ा हो सकता है।
डंकन कैल्वर्ट


13

के बीच का अंतर <init>और <clinit>वह यह है कि <init>, निर्माता तरीकों कि एक वस्तु उदाहरण आरंभ के लिए प्रयोग किया जाता है, जबकि <clinit>वर्ग वस्तु ही आरंभ किया जाता है। उदाहरण के लिए किसी भी staticवर्ग स्तर के खेतों का <clinit>प्रारंभिक वर्गीकरण तब किया जाता है जब कक्षा को लोड किया जाता है और उन्हें काट दिया जाता है।


1

बस जोड़ने के लिए यदि आप Class.forName विधि का उपयोग करते हैं, तो यह केवल कक्षा को सूचित करता है। तो इस पद्धति के भीतर से, यह केवल कॉल करने के लिए एक क्लिनिक बनाता है और जब आप 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();
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.