Java Language
autoboxing
खोज…
परिचय
ऑटोबॉक्सिंग एक स्वचालित रूपांतरण है जो जावा कंपाइलर आदिम प्रकारों और उनके संबंधित ऑब्जेक्ट रैपर वर्गों के बीच बनाता है। उदाहरण, अभिसरण int -> पूर्णांक, डबल -> डबल ... यदि रूपांतरण दूसरे तरीके से जाता है, तो इसे अनबॉक्सिंग कहा जाता है। आमतौर पर, इसका उपयोग संग्रह में उन वस्तुओं के अलावा नहीं किया जा सकता है, जहां संग्रह में स्थापित करने से पहले बॉक्सिंग आदिम प्रकार की आवश्यकता होती है।
टिप्पणियों
जब आपके कोड में अक्सर उपयोग किया जाता है तो ऑटोबॉक्सिंग में प्रदर्शन समस्याएं हो सकती हैं।
आंतरिक और पूर्णांक का उपयोग करना
जैसा कि आप उपयोगिता वर्गों के साथ सामान्य प्रकार का उपयोग करते हैं, आप अक्सर पा सकते हैं कि ऑब्जेक्ट प्रकार के रूप में निर्दिष्ट किए जाने पर संख्या प्रकार बहुत उपयोगी नहीं होते हैं, क्योंकि वे अपने आदिम समकक्षों के बराबर नहीं होते हैं।
List<Integer> ints = new ArrayList<Integer>();
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
}
उपर्युक्त उदाहरण में, वस्तु का मूल्य अनइंस्टॉल और अनइंस्टॉलिज्ड है और इस प्रकार रनटाइम पर प्रोग्राम शून्य पॉइंटर अपवाद में चलेगा। ऊपर दिए गए उदाहरण से स्पष्ट है कि ऑब्जेक्ट के मूल्य को कभी भी अनइंस्टॉल और अनइंस्टॉल नहीं छोड़ा जाना चाहिए।