बॉक्सिंग और अनबॉक्सिंग क्या है और ट्रेड ऑफ क्या हैं?


135

मैं स्पष्ट, संक्षिप्त और सटीक उत्तर की तलाश में हूं।

आदर्श रूप में वास्तविक उत्तर के रूप में, हालांकि अच्छी व्याख्याओं के लिए लिंक का स्वागत है।


2
क्या यह वास्तव में भाषा-अज्ञेय है?
हेन्क होल्टरमैन

3
@ हेंकहॉल्टरमैन यह निश्चित रूप से विशिष्ट भाषा नहीं है, हालांकि यह सभी भाषाओं के लिए भी प्रासंगिक नहीं है - उदाहरण के लिए, अधिकांश गतिशील रूप से टाइप की गई भाषाओं के लिए अंतर अप्रासंगिक होगा। मुझे यकीन नहीं है कि इसके बजाय क्या टैग इस्तेमाल किया जा सकता है - language-but-not-type-agnostic? static-language-agnostic? मुझे यकीन नहीं है कि एसओ को भेद की आवश्यकता है; मेटा के लिए एक अच्छा सवाल हो सकता है।
कीथ

जवाबों:


189

बॉक्सिंग मान डेटा संरचनाएं हैं जो आदिम प्रकारों के आसपास न्यूनतम आवरण हैं *। बॉक्सिंग वैल्यू को आमतौर पर हीप पर ऑब्जेक्ट के लिए पॉइंटर्स के रूप में स्टोर किया जाता है

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

जावा और हास्केल जेनेरिक संग्रहों में अनबॉक्सिड वैल्यूज़ नहीं हो सकती हैं। .NET में जेनेरिक कलेक्शन बिना किसी पेनल्टी के अनबॉक्स वैल्यूज को होल्ड कर सकते हैं। जहाँ Java के जेनरिक का उपयोग केवल संकलन-समय प्रकार की जाँच के लिए किया जाता है, .NET प्रत्येक सामान्य प्रकार के लिए विशिष्ट कक्षाएं चलाएगा

जावा और हास्केल में अनबॉक्ड ऐरे हैं, लेकिन वे अन्य संग्रह की तुलना में कम सुविधाजनक हैं। हालांकि, जब चोटी के प्रदर्शन की आवश्यकता होती है तो बॉक्सिंग और अनबॉक्सिंग के ओवरहेड से बचने के लिए थोड़ी असुविधा के लायक है।

* इस चर्चा के लिए, एक आदिम मूल्य वह है जिसे कॉल स्टैक पर संग्रहीत किया जा सकता है , बजाय एक सूचक के रूप में ढेर पर एक मूल्य के लिए संग्रहीत किया । अक्सर यह सिर्फ मशीन के प्रकार (इन्टस, फ्लोट्स इत्यादि), स्ट्रक्चर्स, और कभी-कभी स्टैटिक आकार के ऐरे होते हैं। .NET-भूमि उन्हें मूल्य प्रकार (संदर्भ प्रकार के विपरीत) कहती है। जावा लोग उन्हें आदिम प्रकार कहते हैं। हास्केलियन बस उन्हें अनबॉक्स कहते हैं।

** मैं इस जवाब में जावा, हास्केल और सी # पर भी ध्यान केंद्रित कर रहा हूं, क्योंकि यही मैं जानता हूं। इसके लायक क्या है, पायथन, रूबी, और जावास्क्रिप्ट सभी विशेष रूप से बॉक्सिंग मूल्य हैं। इसे "सब कुछ एक वस्तु है" दृष्टिकोण *** के रूप में भी जाना जाता है।

*** कैविट: कुछ मामलों में पर्याप्त रूप से उन्नत संकलक / जेआईटी वास्तव में यह पता लगा सकता है कि स्रोत को देखते समय एक शब्द जो शब्दार्थ रूप से बॉक्सिंग किया गया है, सुरक्षित रूप से रनटाइम पर अनबॉक्स किया गया मान हो सकता है। संक्षेप में, शानदार भाषा कार्यान्वयनकर्ताओं के लिए धन्यवाद आपके बक्से कभी-कभी स्वतंत्र होते हैं।


हालांकि एक बॉक्सिंग मूल्य, सीएलआर या जो भी फॉर्म बॉक्सिंग मूल्यों को प्राप्त करता है, उससे क्या लाभ होता है?
पॉजिटिव

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

2
जावास्क्रिप्ट को तथाकथित टाइपेज़ (नई UInt32Array आदि) कहा जाता है, जो कि अनबॉक्स्ड इनट्स और फ़्लोट्स के एरेज़ हैं।
नोनपेकॉप


72

बॉक्सिंग और अनबॉक्सिंग एक आदिम मूल्य को ऑब्जेक्ट ओरिएंटेड रैपर क्लास (बॉक्सिंग) में परिवर्तित करने, या ऑब्जेक्ट ओरिएंटेड रैपर क्लास से वापस आदिम वैल्यू (अनबॉक्सिंग) में वैल्यू कन्वर्ट करने की प्रक्रिया है।

उदाहरण के लिए, जावा में, आपको एक intमान Integer(बॉक्सिंग) में बदलने की आवश्यकता हो सकती है यदि आप इसे स्टोर करना चाहते हैं Collectionक्योंकि आदिम को Collectionकेवल वस्तुओं में संग्रहीत नहीं किया जा सकता है । लेकिन जब आप इसे वापस प्राप्त करना चाहते हैं तो आप Collectionमूल्य को एक के रूप में प्राप्त करना चाहते हैं intऔर Integerऐसा नहीं कर सकते कि आप इसे अनबॉक्स कर देंगे।

बॉक्सिंग और अनबॉक्सिंग स्वाभाविक रूप से खराब नहीं है , लेकिन यह एक व्यापार है। भाषा के कार्यान्वयन के आधार पर, यह केवल प्राथमिकताओं का उपयोग करने की तुलना में धीमा और अधिक गहन हो सकता है। हालांकि, यह आपको उच्च स्तरीय डेटा संरचनाओं का उपयोग करने और अपने कोड में अधिक लचीलापन प्राप्त करने की अनुमति भी दे सकता है।

इन दिनों, यह जावा (और अन्य भाषा के) "ऑटोबॉक्सिंग / ऑटोऑनबॉक्सिंग" फीचर के संदर्भ में सबसे अधिक चर्चा में है। यहाँ ऑटोबॉक्सिंग की एक जावा केंद्रित व्याख्या है


23

कुल मिलाकर:

अक्सर आप इस बात पर भरोसा नहीं कर सकते हैं कि किसी फ़ंक्शन का चर किस प्रकार का उपभोग करेगा, इसलिए आपको एक ऑब्जेक्ट चर का उपयोग करने की आवश्यकता होती है जो सबसे कम आम भाजक - .Net में इसका विस्तार होता है object

हालांकि objectएक वर्ग है और अपनी सामग्री को संदर्भ के रूप में संग्रहीत करता है।

List<int> notBoxed = new List<int> { 1, 2, 3 };
int i = notBoxed[1]; // this is the actual value

List<object> boxed = new List<object> { 1, 2, 3 };
int j = (int) boxed[1]; // this is an object that can be 'unboxed' to an int

जबकि ये दोनों समान जानकारी रखते हैं दूसरी सूची बड़ी और धीमी है। दूसरी सूची में प्रत्येक मूल्य वास्तव में एक का एक संदर्भ है objectजो धारण करता है int

इसे बॉक्सिंग कहा जाता है क्योंकि intयह लिपटे हुए है object। जब इसकी कास्ट बैक intअनबॉक्स हो जाती है - तो इसे वापस वैल्यू में बदल दिया जाता है।

मान प्रकारों के लिए (अर्थात सभी structs) यह धीमा है, और संभावित रूप से बहुत अधिक स्थान का उपयोग करता है।

संदर्भ प्रकारों (यानी सभी classes) के लिए यह एक समस्या से काफी कम है, क्योंकि वे एक संदर्भ के रूप में वैसे भी संग्रहीत हैं।

एक बॉक्सेड वैल्यू टाइप के साथ एक और समस्या यह है कि यह स्पष्ट नहीं है कि आप बॉक्स के साथ काम कर रहे हैं, बल्कि मूल्य के बजाय। जब आप दो की तुलना structsकरते हैं तो आप मूल्यों की तुलना कर रहे हैं, लेकिन जब आप दो की तुलना करते हैं classes(तब डिफ़ॉल्ट रूप से) आप संदर्भ की तुलना कर रहे हैं - यानी ये वही उदाहरण हैं?

बॉक्सिंग मूल्य प्रकारों के साथ काम करते समय यह भ्रामक हो सकता है:

int a = 7;
int b = 7;

if(a == b) // Evaluates to true, because a and b have the same value

object c = (object) 7;
object d = (object) 7;

if(c == d) // Evaluates to false, because c and d are different instances

आसपास काम करना आसान है:

if(c.Equals(d)) // Evaluates to true because it calls the underlying int's equals

if(((int) c) == ((int) d)) // Evaluates to true once the values are cast

हालाँकि यह एक और बात है कि बॉक्सिंग वैल्यू से निपटते समय सावधान रहना चाहिए।


1
Vb.net में, समानता शब्दार्थ के बीच अंतर स्पष्ट है, Objectसमानता ऑपरेटर को लागू नहीं करता है, लेकिन Isऑपरेटर के साथ वर्ग प्रकार की तुलना की जा सकती है ; इसके विपरीत, Int32समानता ऑपरेटर के साथ उपयोग किया जा सकता है, लेकिन नहीं Is। यह भेद यह स्पष्ट करता है कि किस प्रकार की तुलना की जा रही है।
सुपरकैट

4

Boxingमान प्रकार को संदर्भ प्रकार में बदलने की प्रक्रिया है। जबकि Unboxingएक संदर्भ प्रकार का मूल्य प्रकार में रूपांतरण होता है।

EX: int i = 123;
    object o = i;// Boxing
    int j = (int)o;// UnBoxing

मूल्य प्रकार हैं: int, charऔर structures, enumerations। संदर्भ प्रकार हैं: Classes, interfaces, arrays, stringsऔरobjects


3

.NET FCL सामान्य संग्रह:

List<T>
Dictionary<TKey, UValue>
SortedDictionary<TKey, UValue>
Stack<T>
Queue<T>
LinkedList<T>

सभी को पिछले संग्रह कार्यान्वयन में मुक्केबाजी और अनबॉक्सिंग के प्रदर्शन के मुद्दों को दूर करने के लिए डिज़ाइन किया गया था।

अधिक के लिए, अध्याय 16, CLR को C # (द्वितीय संस्करण) के माध्यम से देखें ।


1

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

int i=123;
object o=(object)i; //Boxing

o=123;
i=(int)o; //Unboxing.

जावास्क्रिप्ट में, var ii = 123; typeof ii रिटर्न numbervar iiObj = new Number(123); typeof iiObjलौटता है objecttypeof ii + iiObjलौटता है number। तो यह बॉक्सिंग के बराबर जावास्क्रिप्ट है। अंकगणितीय प्रदर्शन करने और एक अनबॉक्सित मान वापस करने के लिए iiObj स्वचालित रूप से एक आदिम संख्या (अनबॉक्स) में परिवर्तित हो गया था।
पाट्स

-2

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

public class TestAutoboxNPE
{
    public static void main(String[] args)
    {
        Integer i = null;

        // .. do some other stuff and forget to initialise i

        i = addOne(i);           // Whoa! NPE!
    }

    public static int addOne(int i)
    {
        return i + 1;
    }
}

यह सिर्फ बुरा कोड है, और इसका ऑटोबॉक्सिंग से कोई लेना-देना नहीं है। चर iको समय से पहले आरंभीकृत किया जाता है। या तो इसे एक खाली घोषणा ( Integer i;) करें ताकि संकलक इंगित कर सके कि आप इसे आरंभीकृत करना भूल गए हैं, या जब तक आप इसका मूल्य नहीं जानते तब तक इसे घोषित करने की प्रतीक्षा करें।
erickson

हम्म, और अगर मैं एक कोशिश पकड़ने ब्लॉक के अंदर कुछ inbetween करता हूं, तो संकलक मुझे इसे कुछ के साथ आरंभ करने के लिए मजबूर करेगा। यह कोई वास्तविक कोड नहीं है - यह एक उदाहरण है कि यह कैसे हो सकता है।
PEELY

यह क्या प्रदर्शित करता है? इंटेगर ऑब्जेक्ट का उपयोग करने का कोई कारण नहीं है। इसके बजाय अब आपको एक संभावित NullPointer से निपटना होगा।
रिचर्ड क्लेटन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.