खोज…


परिचय

ऑटोबॉक्सिंग एक स्वचालित रूपांतरण है जो जावा कंपाइलर आदिम प्रकारों और उनके संबंधित ऑब्जेक्ट रैपर वर्गों के बीच बनाता है। उदाहरण, अभिसरण int -> पूर्णांक, डबल -> डबल ... यदि रूपांतरण दूसरे तरीके से जाता है, तो इसे अनबॉक्सिंग कहा जाता है। आमतौर पर, इसका उपयोग संग्रह में उन वस्तुओं के अलावा नहीं किया जा सकता है, जहां संग्रह में स्थापित करने से पहले बॉक्सिंग आदिम प्रकार की आवश्यकता होती है।

टिप्पणियों

जब आपके कोड में अक्सर उपयोग किया जाता है तो ऑटोबॉक्सिंग में प्रदर्शन समस्याएं हो सकती हैं।

आंतरिक और पूर्णांक का उपयोग करना

जैसा कि आप उपयोगिता वर्गों के साथ सामान्य प्रकार का उपयोग करते हैं, आप अक्सर पा सकते हैं कि ऑब्जेक्ट प्रकार के रूप में निर्दिष्ट किए जाने पर संख्या प्रकार बहुत उपयोगी नहीं होते हैं, क्योंकि वे अपने आदिम समकक्षों के बराबर नहीं होते हैं।

List<Integer> ints = new ArrayList<Integer>();
जावा एसई 7
List<Integer> ints = new ArrayList<>();

सौभाग्य से, भाव कि के रूप में मूल्यांकित int एक के स्थान पर इस्तेमाल किया जा सकता Integer जब यह आवश्यक है।

for (int i = 0; i < 10; i++)
    ints.add(i);

ints.add(i); कथन इसके बराबर है:

ints.add(Integer.valueOf(i));

और Integer#valueOf से प्रॉपर्टीज को बरकरार रखता है जैसे कि उसी Integer ऑब्जेक्ट को जेवीएम द्वारा कैश किया जाता है जब वह नंबर कैशिंग रेंज के भीतर होता है।

यह भी इसके लिए लागू होता है:

  • byte और Byte
  • short और Short
  • float और Float
  • double और Double
  • long और Long
  • char और Character
  • boolean और Boolean

हालांकि, अस्पष्ट स्थितियों में देखभाल की जानी चाहिए। निम्नलिखित कोड पर विचार करें:

List<Integer> ints = new ArrayList<Integer>();
ints.add(1);
ints.add(2);
ints.add(3);
ints.remove(1); // ints is now [1, 3]

java.util.List इंटरफ़ेस में एक remove(int index) ( List इंटरफ़ेस विधि) और एक remove(Object o) ( java.util.Collection से विरासत में मिली विधि)। इस मामले में कोई मुक्केबाजी नहीं होती है और remove(int index) कहा जाता है।

अजीब जावा कोड से रेंज में मूल्यों के साथ पूर्णांकों autoboxing की वजह से व्यवहार की एक और उदाहरण -128 को 127 :

Integer a = 127;
Integer b = 127;
Integer c = 128;
Integer d = 128;
System.out.println(a == b); // true
System.out.println(c <= d); // true
System.out.println(c >= d); // true
System.out.println(c == d); // false

ऐसा इसलिए होता है क्योंकि >= संचालक intValue() कहता है जो int == जबकि int संदर्भ देता है , int मान नहीं।

डिफ़ॉल्ट रूप से, जावा कैश का मान रेंज [-128, 127] , इसलिए ऑपरेटर == इसलिए काम करता है क्योंकि इस श्रेणी में Integers समान वस्तुओं के संदर्भ में होता है यदि उनका मान समान है। -XX:AutoBoxCacheMax रेंज का अधिकतम मान -XX:AutoBoxCacheMax साथ परिभाषित किया जा सकता है -XX:AutoBoxCacheMax JVM विकल्प। इसलिए, यदि आप प्रोग्राम को -XX:AutoBoxCacheMax=1000 साथ -XX:AutoBoxCacheMax=1000 , तो निम्न कोड true होगा:

Integer a = 1000;
Integer b = 1000;
System.out.println(a == b); // true

अगर स्टेटमेंट में बूलियन का उपयोग करना

ऑटो अनबॉक्सिंग के कारण, if स्टेटमेंट में Boolean उपयोग कर सकता है:

Boolean a = Boolean.TRUE;
if (a) { // a gets converted to boolean
    System.out.println("It works!");
}

के लिए है कि काम करता है while , do while और में हालत for बयान में अच्छी तरह से।

ध्यान दें कि, यदि Boolean null , तो रूपांतरण में एक NullPointerException डाली जाएगी।

ऑटो-अनबॉक्सिंग NullPointerException को जन्म दे सकता है

यह कोड संकलित करता है:

Integer arg = null;
int x = arg;

लेकिन यह दूसरी लाइन पर एक java.lang.NullPointerException साथ रनटाइम पर क्रैश हो जाएगा।

समस्या यह है कि एक आदिम int में एक null मान नहीं हो सकता है।

यह एक न्यूनतर उदाहरण है, लेकिन व्यवहार में यह अक्सर अधिक परिष्कृत रूपों में प्रकट होता है। NullPointerException बहुत सहज नहीं है और अक्सर ऐसे बग्स का पता लगाने में बहुत कम मदद मिलती है।

ऑटोबॉक्सिंग और देखभाल के साथ ऑटो-अनबॉक्सिंग पर भरोसा करें, यह सुनिश्चित करें कि अनबॉक्स किए गए मूल्यों में रनटाइम पर null मान नहीं होंगे।

ऑटोबॉक्सिंग की मेमोरी और कम्प्यूटेशनल ओवरहेड

ऑटोबॉक्सिंग एक पर्याप्त मेमोरी ओवरहेड पर आ सकता है। उदाहरण के लिए:

Map<Integer, Integer> square = new HashMap<Integer, Integer>();
for(int i = 256; i < 1024; i++) {
    square.put(i, i * i); // Autoboxing of large integers
}

आम तौर पर पर्याप्त मात्रा में मेमोरी (6k वास्तविक डेटा के लिए लगभग 60kb) का उपभोग करेगा।

इसके अलावा, बॉक्सिंग पूर्णांकों को आमतौर पर मेमोरी में अतिरिक्त राउंड-ट्रिप की आवश्यकता होती है, और इस तरह सीपीयू कैश कम प्रभावी हो जाता है। ऊपर दिए गए उदाहरण में, एक्सेस की गई मेमोरी पाँच अलग-अलग स्थानों पर फैली हुई है, जो पूरी तरह से मेमोरी के अलग-अलग क्षेत्रों में हो सकती हैं: 1. HashMap ऑब्जेक्ट, 2. मैप की Entry[] table ऑब्जेक्ट, 3. Entry ऑब्जेक्ट, 4. प्रविष्टि key वस्तु (आदिम कुंजी बॉक्सिंग), 5. प्रविष्टि value वस्तु (आदिम मूल्य बॉक्सिंग)।

class Example {
  int primitive; // Stored directly in the class `Example`
  Integer boxed; // Reference to another memory location
}

boxed को पढ़ने के लिए दो मेमोरी एक्सेस की आवश्यकता होती है, एक ही primitive एक्सेस करना।

इस मानचित्र से डेटा प्राप्त करते समय, प्रतीत होता है कि निर्दोष कोड

int sumOfSquares = 0;
for(int i = 256; i < 1024; i++) {
    sumOfSquares += square.get(i);
}

के बराबर है:

int sumOfSquares = 0;
for(int i = 256; i < 1024; i++) {
    sumOfSquares += square.get(Integer.valueOf(i)).intValue();
}

आमतौर पर, उपरोक्त कोड हर Map#get(Integer) ऑपरेशन के लिए एक Integer वस्तु के निर्माण और कचरा संग्रह का कारण बनता है। (अधिक जानकारी के लिए नीचे नोट देखें।)

इस ओवरहेड को कम करने के लिए, कई पुस्तकालय आदिम प्रकारों के लिए अनुकूलित संग्रह प्रदान करते हैं जिन्हें बॉक्सिंग की आवश्यकता नहीं होती है। बॉक्सिंग ओवरहेड से बचने के अलावा, इन संग्रह में प्रति प्रविष्टि लगभग 4x कम मेमोरी की आवश्यकता होगी। जबकि जावा हॉटस्पॉट ढेर के बजाय स्टैक पर वस्तुओं के साथ काम करके ऑटोबॉक्सिंग को अनुकूलित करने में सक्षम हो सकता है, यह मेमोरी ओवरहेड और परिणामस्वरूप मेमोरी इनडायरेक्शन को अनुकूलित करना संभव नहीं है।

जावा 8 स्ट्रीम में आदिम डेटा प्रकारों के लिए अनुकूलित इंटरफेस भी हैं, जैसे कि IntStream जिसमें बॉक्सिंग की आवश्यकता नहीं होती है।

नोट: एक सामान्य जावा रनटाइम Integer और अन्य आदिम आवरण आवरण की एक साधारण कैश को बनाए रखता है, जिसका उपयोग valueOf फ़ैक्टरी विधियों और valueOf द्वारा किया जाता है। Integer , इस कैश की डिफ़ॉल्ट सीमा -128 है +127 तक। कुछ JVM कैश आकार / सीमा को बदलने के लिए एक JVM कमांड-लाइन विकल्प प्रदान करते हैं।

विभिन्न मामलों जब इंटेगर और इंट का उपयोग किया जा सकता है

केस 1: विधि तर्कों के स्थान पर उपयोग करते समय।

यदि किसी विधि को तर्क के रूप में आवरण वर्ग की एक वस्तु की आवश्यकता होती है। तब परस्पर संबंध में तर्क को संबंधित आदिम प्रकार के एक चर को पारित किया जा सकता है और इसके विपरीत।

उदाहरण:

int i;
Integer j;
void ex_method(Integer i)//Is a valid statement
void ex_method1(int j)//Is a valid statement

केस 2: रिटर्न वैल्यू पास करते समय:

जब कोई विधि एक आदिम प्रकार के चर को लौटाती है तो संबंधित रैपर क्लास की एक वस्तु को रिटर्न वैल्यू इंटरचेंजबली और इसके विपरीत दिया जा सकता है।

उदाहरण:

int i;
Integer j;
int ex_method()
{...
return j;}//Is a valid statement
Integer ex_method1()
{...
return i;//Is a valid statement
}

केस 3: ऑपरेशन करते समय।

जब भी संख्याओं पर परिचालन प्रदर्शन किया जाता है तो संबंधित आवरण वर्ग के आदिम प्रकार के चर और वस्तु का परस्पर विनिमय किया जा सकता है।

int i=5;
Integer j=new Integer(7);
int k=i+j;//Is a valid statement
Integer m=i+j;//Is also a valid statement

नुकसान : रैपर क्लास की किसी वस्तु के मूल्य को इनिशियलाइज़ या असाइन करना याद रखें।

रैपर क्लास ऑब्जेक्ट और आदिम वैरिएबल का उपयोग करते समय, इंटरचेंज करने के लिए कभी भी भूलना या याद नहीं करना चाहिए या रैपर क्लास ऑब्जेक्ट को वैल्यू को इनिशियलाइज़ या असाइन नहीं करना चाहिए, अन्यथा यह रनटाइम पर पॉइलर पॉइंटर अपवाद को जन्म दे सकता है।

उदाहरण:

public class Test{
    Integer i;
    int j;
    public void met()
    {j=i;//Null pointer exception
    SOP(j);
    SOP(i);}   
    public static void main(String[] args)
    {Test t=new Test();
    t.go();//Null pointer exception
    }

उपर्युक्त उदाहरण में, वस्तु का मूल्य अनइंस्टॉल और अनइंस्टॉलिज्ड है और इस प्रकार रनटाइम पर प्रोग्राम शून्य पॉइंटर अपवाद में चलेगा। ऊपर दिए गए उदाहरण से स्पष्ट है कि ऑब्जेक्ट के मूल्य को कभी भी अनइंस्टॉल और अनइंस्टॉल नहीं छोड़ा जाना चाहिए।



Modified text is an extract of the original Stack Overflow Documentation
के तहत लाइसेंस प्राप्त है CC BY-SA 3.0
से संबद्ध नहीं है Stack Overflow