जावा एपीआई का उपयोग क्यों int
, जब short
या यहां तक byte
कि पर्याप्त होगा?
उदाहरण: DAY_OF_WEEK
वर्ग Calendar
उपयोग में क्षेत्र int
।
यदि अंतर बहुत कम है, तो उन डेटाटाइप्स ( short
, int
) बिल्कुल क्यों मौजूद हैं?
जावा एपीआई का उपयोग क्यों int
, जब short
या यहां तक byte
कि पर्याप्त होगा?
उदाहरण: DAY_OF_WEEK
वर्ग Calendar
उपयोग में क्षेत्र int
।
यदि अंतर बहुत कम है, तो उन डेटाटाइप्स ( short
, int
) बिल्कुल क्यों मौजूद हैं?
जवाबों:
कुछ कारणों को पहले ही बताया जा चुका है। उदाहरण के लिए, तथ्य यह है कि "... (लगभग) बाइट पर सभी संचालन, संक्षिप्त इन आदिमों को बढ़ावा देंगे int" । हालाँकि, अगला अगला प्रश्न यह होगा: इन प्रकारों को बढ़ावा क्यों दिया जाता है int
?
तो एक स्तर पर गहराई तक जाने के लिए: उत्तर केवल जावा वर्चुअल मशीन इंस्ट्रक्शन सेट से संबंधित हो सकता है। जैसा कि जावा वर्चुअल मशीन विनिर्देश में तालिका में संक्षेपित किया गया है , सभी अभिन्न अंकगणितीय संचालन, जैसे जोड़ना, विभाजित करना और अन्य, केवल प्रकार int
और प्रकार के लिए उपलब्ध हैं long
, न कि छोटे प्रकार के लिए।
(एक तरफ: छोटे प्रकार ( byte
और short
) मूल रूप से केवल सरणियों के लिए अभिप्रेत हैं । एक सरणी की तरह new byte[1000]
1000 बाइट्स लेंगे, और एक सरणी की तरह new int[1000]
4000 बाइट्स लेंगे)
अब, निश्चित रूप से, कोई यह कह सकता है कि "... स्पष्ट अगला प्रश्न होगा: ये निर्देश केवल (और ) के लिए क्यों दिए गए हैं ?" int
long
।
एक कारण ऊपर उल्लिखित जेवीएम स्पेक में उल्लिखित है:
यदि प्रत्येक टाइप किए गए निर्देश ने जावा वर्चुअल मशीन के रन-टाइम डेटा प्रकारों का समर्थन किया है, तो बाइट में प्रतिनिधित्व किए जाने की तुलना में अधिक निर्देश होंगे।
इसके अतिरिक्त, जावा वर्चुअल मशीन को वास्तविक प्रोसेसर का अमूर्त माना जा सकता है। और छोटे प्रकारों के लिए समर्पित अरिथमेटिक लॉजिक यूनिट शुरू करना इस प्रयास के लायक नहीं होगा: इसके लिए अतिरिक्त ट्रांजिस्टर की आवश्यकता होगी, लेकिन यह अभी भी केवल एक घड़ी चक्र में एक जोड़ को निष्पादित कर सकता है। जब JVM का डिज़ाइन किया गया था, तो यह एक प्रमुख वास्तुशिल्प था, जो 32 बिट के लिए सही था int
। (एक 64 बिट long
मान को शामिल करने वाले ऑपरेशन एक विशेष मामले के रूप में कार्यान्वित किए जाते हैं)।
(ध्यान दें: अंतिम पैराग्राफ थोड़ा सुस्पष्ट है, संभावित वेक्टराइजेशन आदि पर विचार करते हुए, लेकिन प्रोसेसर डिजाइन विषयों में बहुत अधिक गोता लगाने के बिना मूल विचार देना चाहिए)
संपादित करें: एक लघु परिशिष्ट, प्रश्न से उदाहरण पर ध्यान केंद्रित करना, लेकिन अधिक सामान्य अर्थ में: कोई यह भी पूछ सकता है कि क्या छोटे प्रकारों का उपयोग करके खेतों को संग्रहीत करना फायदेमंद नहीं होगा । उदाहरण के लिए, कोई सोच सकता है कि स्मृति Calendar.DAY_OF_WEEK
को एक के रूप में संग्रहीत करके बचाया जा सकता है byte
। लेकिन यहां, जावा क्लास फाइल फॉर्मेट चलन में आता है: क्लास फाइल में सभी फील्ड्स कम से कम एक "स्लॉट" पर रहती हैं, जिसका आकार एक int
(32 बिट्स) होता है। ("विस्तृत" फ़ील्ड, double
और long
, दो स्लॉट्स पर कब्जा)। तो स्पष्ट रूप से किसी क्षेत्र को घोषित करने short
या byte
किसी भी स्मृति को बचाने के लिए नहीं होगा।
int
। यदि आपके पास किसी अन्य कार्यान्वयन का संदर्भ है, तो मैं उत्तर को अपडेट करूंगा और तदनुसार लिंक डालूंगा।
(लगभग) सभी ऑपरेशन byte
, short
उन्हें बढ़ावा देंगे int
, उदाहरण के लिए, आप नहीं लिख सकते हैं:
short x = 1;
short y = 2;
short z = x + y; //error
उपयोग करते समय अंकगणित आसान और सरल होते हैं int
, जिन्हें डालने की आवश्यकता नहीं होती है।
अंतरिक्ष के संदर्भ में, यह बहुत कम अंतर रखता है। byte
और short
चीजों को उलझाएंगे, मुझे नहीं लगता कि यह सूक्ष्म अनुकूलन इसके लायक है क्योंकि हम एक निश्चित मात्रा में चर के बारे में बात कर रहे हैं।
byte
जब आप एम्बेडेड उपकरणों के लिए प्रोग्राम करते हैं या फाइलों / नेटवर्कों से निपटने के लिए प्रासंगिक और उपयोगी होते हैं। इसके अलावा ये आदिमियां सीमित हैं, अगर भविष्य में गणना अपनी सीमा से अधिक हो जाए तो क्या होगा? Calendar
वर्ग के लिए एक विस्तार के बारे में सोचने की कोशिश करें जो बड़ी संख्या में विकसित हो सकता है।
यह भी ध्यान रखें कि एक 64 बिट प्रोसेसर में, स्थानीय लोगों रजिस्टरों में सहेज लिया जाएगा और किसी भी संसाधनों का उपयोग नहीं होगा, इसलिए का उपयोग कर int
, short
और अन्य पुरातन सब पर कोई फर्क नहीं होगा। इसके अलावा, कई जावा कार्यान्वयन संरेखित चर * (और वस्तुओं)।
* byte
और short
उसी स्थान पर कब्जा करें जैसे int
कि वे स्थानीय चर, वर्ग चर या उदाहरण चर हैं। क्यों? क्योंकि (अधिकांश) कंप्यूटर सिस्टम में, चर पते संरेखित होते हैं , इसलिए उदाहरण के लिए यदि आप एक बाइट का उपयोग करते हैं, तो आप वास्तव में दो बाइट्स के साथ समाप्त होंगे - एक चर के लिए और दूसरा पैडिंग के लिए।
दूसरी ओर, सरणियों में, byte
1 बाइट लें, short
2 बाइट लें और int
चार बाइट लें, क्योंकि एरे में केवल शुरुआत होती है और शायद इसके अंत को संरेखित करना होता है। उदाहरण के लिए, यदि आप उपयोग करना चाहते हैं तो यह एक अंतर बना देगा System.arraycopy()
, फिर आप वास्तव में एक प्रदर्शन अंतर पर ध्यान देंगे।
क्योंकि शॉर्ट्स की तुलना में पूर्णांकों का उपयोग करते समय अंकगणितीय संचालन आसान होता है। मान लें कि स्थिरांक वास्तव में short
मूल्यों द्वारा मॉडलिंग की गई थी । फिर आपको इस तरीके से एपीआई का उपयोग करना होगा:
short month = Calendar.JUNE;
month = month + (short) 1; // is july
स्पष्ट कास्टिंग पर ध्यान दें। int
जब वे अंकगणितीय परिचालनों में उपयोग किए जाते हैं, तो लघु मानों को मूल रूप से उन मूल्यों को बढ़ावा दिया जाता है। (ऑपरेंड स्टैक पर, शॉर्ट्स को भी इन्ट्स के रूप में व्यक्त किया जाता है।) यह उपयोग करने के लिए काफी बोझिल होगा, यही वजह है कि int
मूल्यों को अक्सर स्थिरांक के लिए पसंद किया जाता है।
इसकी तुलना में, भंडारण दक्षता में लाभ कम से कम है क्योंकि केवल ऐसे स्थिरांक की एक निश्चित संख्या मौजूद है। हम 40 स्थिरांक के बारे में बात कर रहे हैं। से उनके भंडारण बदलने int
के लिए short
चाहेंगे सुरक्षित आप 40 * 16 bit = 80 byte
। आगे के संदर्भ के लिए इस उत्तर को देखें ।
यदि आप उस दर्शन का उपयोग करते हैं जहां अभिन्न स्थिरांक सबसे छोटे प्रकार में संग्रहीत किए जाते हैं जिसमें वे फिट होते हैं, तो जावा में एक गंभीर समस्या होगी: जब भी प्रोग्रामर अभिन्न स्थिरांक का उपयोग करते हुए कोड लिखते हैं, तो उन्हें यह जांचने के लिए अपने कोड पर सावधानीपूर्वक ध्यान देना होगा कि क्या प्रकार स्थिरांक मायने रखता है, और यदि ऐसा है तो दस्तावेज़ में प्रकार देखें और / या जो भी प्रकार के रूपांतरणों की आवश्यकता है।
तो अब जब हमने एक गंभीर समस्या की रूपरेखा तैयार कर ली है, तो उस दर्शन से क्या लाभ हो सकता है? मैं अप्रसन्न हो जाऊंगा यदि उस परिवर्तन का एकमात्र क्रम-पालन प्रभाव होगा, तो प्रतिबिंब के माध्यम से स्थिर दिखने पर आपको किस प्रकार का लाभ मिलेगा। (और, ज़ाहिर है, आलसी / अनजाने प्रोग्रामर द्वारा जो भी त्रुटियां पेश की जाती हैं, वे स्थिरांक के प्रकारों के लिए सही रूप से लेखांकन नहीं करते हैं)
पेशेवरों और विपक्षों का वजन बहुत आसान है: यह एक बुरा दर्शन है।
वर्चुअल मशीन की डिज़ाइन जटिलता एक कार्य है कि यह कितने प्रकार के ऑपरेशन कर सकता है। "गुणा" जैसे निर्देश के चार कार्यान्वयन होने में आसान है - 32-बिट पूर्णांक, 64-बिट पूर्णांक, 32-बिट फ़्लोटिंग-पॉइंट और 64-बिट फ़्लोटिंग-पॉइंट के लिए - इसके अलावा, उपरोक्त, छोटे संख्यात्मक प्रकारों के लिए भी संस्करण। एक और दिलचस्प डिजाइन सवाल यह है कि क्यों कम के बजाय चार प्रकार के होना चाहिए (64-बिट पूर्णांक के साथ सभी पूर्णांक संगणनाएँ करना और / या 64-फ़्लोटिंग-पॉइंट मानों के साथ सभी फ़्लोटिंग-पॉइंट कंप्यूटेशन करना)। 32-बिट पूर्णांक का उपयोग करने का कारण यह है कि जावा से कई प्लेटफार्मों पर चलने की उम्मीद की गई थी जहां 32-बिट प्रकारों पर जल्दी से जल्दी 16-बिट या 8-बिट प्रकार के रूप में कार्य किया जा सकता था, लेकिन 64-बिट प्रकारों पर संचालन का ध्यान दिया जाएगा और धीमा।केवल 32-बिट प्रकार।
32-बिट मानों पर फ्लोटिंग-पॉइंट कंप्यूटेशन करने के लिए, फायदे थोड़े कम स्पष्ट हैं। कुछ प्लेटफ़ॉर्म हैं जहां एक संगणना पसंद हैfloat a=b+c+d;
सभी ऑपरेंड को उच्च-परिशुद्धता प्रकार में परिवर्तित करके, उन्हें जोड़कर और फिर संग्रहण के लिए 32-बिट फ़्लोटिंग-पॉइंट संख्या में परिणाम परिवर्तित करके सबसे तेज़ी से प्रदर्शन किया जा सकता है। अन्य प्लेटफ़ॉर्म हैं जहां 32-बिट फ़्लोटिंग-पॉइंट मानों का उपयोग करके सभी संगणनाओं को निष्पादित करना अधिक कुशल होगा। जावा के रचनाकारों ने तय किया कि सभी प्लेटफार्मों को चीजों को उसी तरह से करने की आवश्यकता होनी चाहिए, और उन्हें हार्डवेयर प्लेटफार्मों का पक्ष लेना चाहिए, जिसके लिए 32-बिट फ़्लोटिंग-पॉइंट संगणना लंबे लोगों की तुलना में तेज़ हैं, भले ही यह गंभीर रूप से विकृत पीसी दोनों की गति से हो और एक विशिष्ट पीसी पर फ्लोटिंग-पॉइंट मैथ की शुद्धता, साथ ही फ्लोटिंग-पॉइंट यूनिट के बिना कई मशीनों पर। नोट, btw, कि बी, सी, और डी के मूल्यों पर निर्भर करता है, उच्च परिशुद्धता मध्यवर्ती संगणनाओं का उपयोग करते हुए जब उपरोक्त अभिव्यक्ति की तरह कंप्यूटिंगfloat a=b+c+d;
कभी-कभी ऐसे परिणाम निकलेंगे जो सभी मध्यवर्ती संचालकों की तुलना में काफी अधिक सटीक होंगे, जिन्हें सटीक रूप से गणना की गई थी float
, लेकिन कभी-कभी ऐसा मूल्य प्राप्त होगा जो कि थोड़ा कम सटीक हो। किसी भी मामले में, सूर्य ने फैसला किया कि सब कुछ उसी तरह किया जाना चाहिए, और उन्होंने न्यूनतम-परिशुद्धता float
मूल्यों का उपयोग करने का विकल्प चुना ।
ध्यान दें कि छोटे डेटा प्रकारों के प्राथमिक लाभ स्पष्ट हो जाते हैं जब उनमें से बड़ी संख्या एक सरणी में एक साथ संग्रहीत होती है; भले ही 64-बिट्स से छोटे प्रकार के अलग-अलग वैरिएबल होने का कोई फायदा न हो, लेकिन ऐसे एरेज़ का होना सार्थक है जो छोटे मूल्यों को अधिक कॉम्पैक्ट रूप से स्टोर कर सकें; एक स्थानीय चर होने के byte
बजाय एक long
सात बाइट्स बचाता है; 1,000,000 संख्याओं की एक सरणी होने से प्रत्येक संख्या एक के byte
बजाय एक संख्या रखती हैlong
लहरों 7,000,000 बाइट्स। चूंकि प्रत्येक सरणी प्रकार को केवल कुछ ऑपरेशनों का समर्थन करने की आवश्यकता होती है (सबसे विशेष रूप से एक आइटम को पढ़ें, एक आइटम को स्टोर करें, किसी सरणी के भीतर कई मदों की प्रतिलिपि बनाएं, या एक सरणी से दूसरे आइटम की श्रेणी की प्रतिलिपि बनाएँ), अधिक होने की अतिरिक्त जटिलता सरणी प्रकार उतने गंभीर नहीं होते हैं जितने सीधे-प्रयोग करने योग्य असतत संख्यात्मक मानों की जटिलता होती है।
वास्तव में, एक छोटा सा फायदा होगा। अगर आपके पास एक है
class MyTimeAndDayOfWeek {
byte dayOfWeek;
byte hour;
byte minute;
byte second;
}
तब एक विशिष्ट जेवीएम पर एक एकल वर्ग के रूप में अधिक स्थान की आवश्यकता होती है int
। मेमोरी खपत अगले 8 या 16 बाइट्स (IIRC, जो कि कॉन्फ़िगर करने योग्य है) के कई चक्कर लगाती है, इसलिए जब वास्तविक बचत होती है तो मामले कम ही होते हैं।
यदि यह Calendar
विधि वापस आती है तो यह वर्ग उपयोग करना थोड़ा आसान होगा byte
। लेकिन ऐसी कोई Calendar
विधियाँ नहीं हैं , get(int)
जो केवल int
अन्य क्षेत्रों के कारण ही लौटनी चाहिए । छोटे प्रकार के प्रत्येक ऑपरेशन को बढ़ावा देता है int
, इसलिए आपको बहुत अधिक कास्टिंग की आवश्यकता होती है।
सबसे शायद, आप या तो छोड़ देंगे या एक int
या लिखने वाले की तरह स्विच करेंगे
void setDayOfWeek(int dayOfWeek) {
this.dayOfWeek = checkedCastToByte(dayOfWeek);
}
फिर DAY_OF_WEEK
कोई बात नहीं, वैसे भी।