2008-08-16 14 views
115

मैं एक स्पष्ट, संक्षिप्त और सटीक उत्तर की तलाश में हूं।मुक्केबाजी और अनबॉक्सिंग क्या है और व्यापार बंद क्या हैं?

आदर्श रूप से वास्तविक उत्तर के रूप में, हालांकि अच्छे स्पष्टीकरण के लिंक आपका स्वागत है।

+2

क्या यह वास्तव में भाषा-अज्ञेयवादी है? –

+3

@ हेनकहोल्टरमैन यह निश्चित रूप से भाषा विशिष्ट नहीं है, हालांकि यह _all_ भाषाओं के लिए भी प्रासंगिक नहीं है - उदाहरण के लिए, अधिकांश गतिशील रूप से टाइप की गई भाषाओं के लिए भेद अप्रासंगिक होगा। मुझे यकीन नहीं है कि इसके बजाय किस टैग का उपयोग किया जा सकता है - 'भाषा-लेकिन-नहीं-प्रकार-अज्ञेयवादी'? 'स्थिर-भाषा-agnostic'? मुझे यकीन नहीं है कि एसओ को भेद की जरूरत है; हालांकि मेटा के लिए एक अच्छा सवाल हो सकता है। – Keith

उत्तर

170

बॉक्स किए गए मान data structures हैं जो primitive types * के आसपास न्यूनतम रैपर हैं। बॉक्स किए गए मान आमतौर पर the heap पर ऑब्जेक्ट्स के पॉइंटर्स के रूप में संग्रहीत किए जाते हैं।

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

जावा और हास्केल जेनेरिक संग्रह में अनबॉक्स किए गए मान नहीं हो सकते हैं। .NET में सामान्य संग्रह बिना दंड के अनबॉक्स किए गए मान रख सकते हैं। जहां जावा के जेनेरिक केवल संकलन-समय प्रकार की जांच के लिए उपयोग किए जाते हैं, .NET generate specific classes for each generic type instantiated at run time होगा।

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

* इस चर्चा के लिए, एक प्राचीन मूल्य वह है जिसे the call stack पर संग्रहीत किया जा सकता है, बजाय ढेर पर एक मूल्य के लिए सूचक के रूप में संग्रहीत किया जा सकता है। अक्सर यह मशीन प्रकार (इंट्स, फ्लोट्स, इत्यादि), structs, और कभी-कभी स्थिर आकार के सरणी होते हैं। .NET-land उन्हें मूल्य प्रकार (संदर्भ प्रकारों के विपरीत) कहते हैं। जावा लोग उन्हें आदिम प्रकार कहते हैं। Haskellions बस उन्हें unboxed बुलाओ।

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

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

+0

क्यों एक बॉक्सिंग मूल्य, सीएलआर या जो कुछ भी मुक्केबाजी मूल्य बनता है? – PositiveGuy

+0

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

+1

जावास्क्रिप्ट ने टाइप किए गए सरणी (नया UInt32Array आदि) कहा है जो अनबॉक्स किए गए इनट्स और फ्लोट के सरणी हैं। – nponeccop

66

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

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

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

इन दिनों, जावा की (और अन्य भाषा) "ऑटोबॉक्सिंग/ऑटोऑनबॉक्सिंग" सुविधा के संदर्भ में यह आमतौर पर चर्चा की जाती है। यहां एक java centric explanation of autoboxing है।

23

नेट में:

अक्सर आप, क्या चर के प्रकार के एक समारोह की खपत होगी पर भरोसा नहीं कर सकते हैं ताकि आप एक वस्तु चर जो सबसे कम आम विभाजक से फैली उपयोग करने की आवश्यकता - नेट में यह है 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 है।

इसे बॉक्स किया जाता है क्योंकि intobject द्वारा लपेटा गया है। जब इसकी कास्ट वापस 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 में, समानता अर्थशास्त्र के बीच भेद स्पष्ट है, 'ऑब्जेक्ट' समानता ऑपरेटर को लागू नहीं करता है, लेकिन वर्ग प्रकारों की तुलना 'Is' ऑपरेटर से की जा सकती है; इसके विपरीत, 'Int32' का उपयोग समानता ऑपरेटर के साथ किया जा सकता है, लेकिन 'Is' नहीं। वह भेद यह स्पष्ट करता है कि किस प्रकार की तुलना की जा रही है। – supercat

110
C# 3.0 In a Nutshell से

:

int x = 9; 
object o = x; // boxing the int 

unboxing है ... रिवर्स:

मुक्केबाजी एक संदर्भ प्रकार में एक मूल्य प्रकार कास्टिंग का कार्य है

// unboxing o 
object o = 9; 
int x = (int)o; 
+33

+1, अब यह ** संक्षिप्त ** है। – Sam

3

नेट FCL सामान्य संग्रह:

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

सभी मुक्केबाजी के प्रदर्शन के मुद्दों पर काबू पाने के लिए तैयार किया गया है और पिछले संग्रह कार्यान्वयन में unboxing रहे थे।

अधिक के लिए, अध्याय 16, CLR via C# (2nd Edition) देखें।

-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; 
    } 
} 
+0

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

+0

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

+0

यह क्या दर्शाता है? इंटीजर ऑब्जेक्ट का उपयोग करने का बिल्कुल कोई कारण नहीं है। इसके बजाय अब आपको एक संभावित नलपोइंटर से निपटना होगा। –

1

बॉक्सिंग एक मान प्रकार के रूपांतरण प्रकार में रूपांतरण प्रकार की प्रक्रिया है।

अनबॉक्सिंग एक संदर्भ प्रकार का एक मान प्रकार में रूपांतरण है।

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

मूल्य प्रकार हैं:
पूर्णांक, चार और संरचनाओं, enumerations। संदर्भ प्रकार हैं: वर्ग, इंटरफेस, सरणियों, तार और वस्तुओं

0

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

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

o=123; 
i=(int)o; //Unboxing. 
संबंधित मुद्दे