जावा में लोग अभी भी आदिम प्रकारों का उपयोग क्यों करते हैं?


163

जावा 5 के बाद से, हमने आदिम प्रकारों की बॉक्सिंग / अनबॉक्सिंग की है ताकि intलिपटे रहें java.lang.Integer, और इसलिए और आगे।

मैं हाल ही में नया जावा परियोजनाओं के एक बहुत देखते हैं (जो निश्चित रूप से , कम से कम संस्करण 5 के एक JRE की आवश्यकता नहीं 6 अगर) है कि प्रयोग कर रहे हैं intके बजाय java.lang.Integer, है, हालांकि यह बाद के उपयोग करने के लिए और अधिक सुविधाजनक है के रूप में यह परिवर्तित करने के लिए कुछ सहायक तरीकों है करने के लिए longमूल्यों एट अल।

कुछ अभी भी जावा में आदिम प्रकारों का उपयोग क्यों करते हैं ? क्या कोई मूर्त लाभ है?


49
कभी स्मृति की खपत और प्रदर्शन के बारे में सोचा?
टेडिल

76
मैंने ऑटोबॉक्सिंग टैग जोड़ा ... और पता चला कि तीन लोग वास्तव में इसका पालन करते हैं। वास्तव में? लोग AUTOBOXING टैग का अनुसरण करते हैं?
corsiKa

4
@glowcoder वे वास्तविक लोग नहीं हैं, वे केवल अमूर्त अवधारणाएं हैं जो SO पर उत्तर देने के लिए एक मानव रूप मानती हैं। :)
बिजिकलोप

9
@ टीके कोचरन ज्यादातर क्योंकि new IntegeR(5) == new Integer(5)नियमों से, झूठ का मूल्यांकन करना चाहिए।
21:39 पर biziclop

10
आदिम प्रकारों के संग्रह के समाधान के लिए GNU ट्रोव या महावत संग्रह या HPPC या ... देखें। हम में से जो लोग गति की परवाह करते हैं वे अधिक आदिम प्रकारों का उपयोग करके अपना समय बिताते हैं, कम नहीं।
bmargulies

जवाबों:


395

जोशुआ बलोच के प्रभावी जावा में , आइटम 5: "अनावश्यक वस्तुओं को बनाने से बचें", वह निम्नलिखित कोड उदाहरण पोस्ट करता है:

public static void main(String[] args) {
    Long sum = 0L; // uses Long, not long
    for (long i = 0; i <= Integer.MAX_VALUE; i++) {
        sum += i;
    }
    System.out.println(sum);
}

और इसे चलाने में 43 सेकंड का समय लगता है। लॉन्ग को आदिम में ले जाना 6.8 सेकंड के लिए नीचे लाता है ... यदि यह कोई संकेत है कि हम प्राइमेटिव का उपयोग क्यों करते हैं।

देशी मूल्य समानता की कमी भी एक चिंता का विषय है ( .equals()तुलना में काफी क्रियात्मक है ==)

biziclop के लिए:

class Biziclop {

    public static void main(String[] args) {
        System.out.println(new Integer(5) == new Integer(5));
        System.out.println(new Integer(500) == new Integer(500));

        System.out.println(Integer.valueOf(5) == Integer.valueOf(5));
        System.out.println(Integer.valueOf(500) == Integer.valueOf(500));
    }
}

का परिणाम:

false
false
true
false

EDIT क्यों (3) रिटर्न trueऔर (4) वापसी करता है false?

क्योंकि वे दो अलग-अलग वस्तुएं हैं। 256 पूर्णांक शून्य के निकटतम है [-128; 127] जेवीएम द्वारा कैश किए गए हैं, इसलिए वे उन लोगों के लिए एक ही वस्तु लौटाते हैं। उस सीमा से परे, हालांकि, वे कैश नहीं हैं, इसलिए एक नई वस्तु बनाई गई है। चीजों को और अधिक जटिल बनाने के लिए, जेएलएस मांग करता है कि कम से कम 256 फ्लाईवेट को कैश किया जाए। जेवीएम कार्यान्वयनकर्ता अपनी इच्छा के अनुसार अधिक जोड़ सकते हैं, जिसका अर्थ है कि यह एक प्रणाली पर चल सकता है जहां निकटतम 1024 कैश किए गए हैं और उनमें से सभी सही हैं ... #awward


54
अब कल्पना करें कि क्या iघोषित किया गया था Long!
कॉलिनड

14
@TREE - वास्तव में वीएम को एक निश्चित सीमा के भीतर फ्लाईवेट बनाने के लिए वीएम की आवश्यकता होती है। लेकिन दुख की बात है कि यह उन्हें उस सीमा का विस्तार करने की अनुमति देता है, जिसका अर्थ है कि कार्यक्रम विभिन्न वीएम पर अलग तरह से व्यवहार कर सकते हैं। क्रॉस प्लेटफॉर्म के लिए इतना ...
डैनियल इयरविकर

12
जावा अधिक से अधिक खराब डिजाइन विकल्पों के साथ, नाली से नीचे चला गया है। ऑटोबॉक्सिंग एक पूर्ण विफलता है, यह न तो मजबूत है, न ही अनुमानित या पोर्टेबल है। मुझे वास्तव में आश्चर्य है कि वे क्या सोच रहे थे ... खूंखार आदिम-वस्तु द्वंद्व को ठीक करने के बजाय वे इसे पहली जगह से भी बदतर बनाने में कामयाब रहे।
पॉप कैटालिन

34
@ कैटालिन मैं आपसे असहमत हूं कि ऑटोबॉक्सिंग एक पूर्ण विफलता है। इसकी कुछ खामियां हैं, जो किसी भी अन्य डिजाइन की तुलना में अलग नहीं है, जिनका उपयोग किया जा सकता था (कुछ भी नहीं है।) वे बहुत स्पष्ट करते हैं कि आप क्या उम्मीद कर सकते हैं और किसी भी अन्य डिजाइन की तरह वे डेवलपर्स से अनुबंधों को जानने और मानने की अपेक्षा करते हैं। उन डिजाइनों की।
corsiKa

9
@NaftuliTzviKay यह "विफलता" नहीं है। वे इसे बहुत स्पष्ट करते हैं कि ==ऑपरेटर Integerअभिव्यक्तियों पर संदर्भ पहचान तुलना करता है और अभिव्यक्ति पर मूल्य समानता तुलना करता intहै। Integer.equals()इस कारण से मौजूद है। आपको किसी भी गैर-आदिम प्रकार के मूल्यों की तुलना करने के लिए कभी भी उपयोग नहीं करना चाहिए ==। यह जावा 101 है।
NullUserException

86

ऑटोपॉक्सिंग से NPEs को स्पॉट करने में मुश्किल हो सकती है

Integer in = null;
...
...
int i = in; // NPE at runtime

ज्यादातर स्थितियों में अशक्त असाइनमेंट inऊपर की तुलना में बहुत कम स्पष्ट है।


43

बॉक्सिंग के प्रकार खराब प्रदर्शन वाले होते हैं और अधिक मेमोरी की आवश्यकता होती है।


40

आदिम प्रकार:

int x = 1000;
int y = 1000;

अब मूल्यांकन करें:

x == y

यह है true। शायद ही आश्चर्य की बात। अब बॉक्सिंग प्रकारों को आज़माएँ:

Integer x = 1000;
Integer y = 1000;

अब मूल्यांकन करें:

x == y

यह है false। शायद। रनटाइम पर निर्भर करता है। क्या यह कारण पर्याप्त है?


36

प्रदर्शन और स्मृति मुद्दों के अलावा, मैं एक और मुद्दे के साथ आना चाहूंगा: Listइंटरफ़ेस बिना टूट जाएगा int
समस्या अतिभारित remove()विधि ( remove(int)बनाम remove(Object)) है। remove(Integer)हमेशा बाद वाले को कॉल करने का संकल्प करेगा, इसलिए आप सूचकांक द्वारा एक तत्व नहीं निकाल सकते।

दूसरी ओर, जोड़ने और हटाने की कोशिश करते समय एक नुकसान होता है int:

final int i = 42;
final List<Integer> list = new ArrayList<Integer>();
list.add(i); // add(Object)
list.remove(i); // remove(int) - Ouch!

7
यह टूट जाएगा, हाँ। हालाँकि, निकालें (int) एक डिज़ाइन दोष IMO है। यदि मिक्स अप की थोड़ी सी भी संभावना है, तो विधि के नाम को कभी भी ओवरलोड नहीं किया जाना चाहिए।

4
@MrBackend मेला काफी। दिलचस्प है, शुरू से Vectorथा removeElementAt(int)remove(int)जावा 1.2 में संग्रह ढांचे के साथ पेश किया गया था।
xehpuk

6
@MrBackend: जब ListAPI डिज़ाइन किया गया था, न तो जेनरिक और न ही ऑटोबॉक्सिंग मौजूद था, इसलिए मिश्रण करने का कोई मौका नहीं था remove(int)और remove(Object)...
Holger

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

27

क्या तुम सच में कल्पना कर सकते हो

  for (int i=0; i<10000; i++) {
      do something
  }

java.lang.Integer के बजाय लूप? एक java.lang.Integer अपरिवर्तनीय है, इसलिए प्रत्येक वृद्धि राउंड लूप ढेर पर एक नया जावा ऑब्जेक्ट बनाएगा, बजाय एकल JVM निर्देश के साथ स्टैक पर इंट वृद्धि। प्रदर्शन शैतानी होगा।

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


19

आदिम प्रकार बहुत तेज़ हैं:

int i;
i++;

पूर्णांक (सभी संख्याएँ और एक स्ट्रिंग भी) एक अपरिवर्तनीय प्रकार है: एक बार निर्मित होने के बाद इसे बदला नहीं जा सकता। यदि iइंटेगर था, तो i++एक नया इंटेगर ऑब्जेक्ट बनायेगा - मेमोरी और प्रोसेसर के मामले में बहुत अधिक महंगा।


आप एक चर को बदलना नहीं चाहते हैं यदि आप i++दूसरे चर पर करते हैं , तो पूर्णांक को ऐसा करने में सक्षम होने के लिए अपरिवर्तनीय होने की आवश्यकता है (या कम से कम यह i++वैसे भी एक नया पूर्णांक ऑब्जेक्ट बनाना होगा)। (और आदिम मूल्य अपरिवर्तनीय हैं, भी - आप इस पर टिप्पणी नहीं करते हैं क्योंकि वे कोई वस्तु नहीं हैं।)
पाओलो एबरमैन 22

4
@ पाओलो: यह कहना कि आदिम मूल्य अपरिवर्तनीय हैं, एक तरह का अर्थहीन है। जब आप एक आदिम चर को नए मान पर पुन: असाइन करते हैं, तो आप कुछ भी नया नहीं बना रहे हैं। कोई स्मृति आवंटन शामिल नहीं है। पीटर की बात का मतलब है: मैं ++ एक आदिम के लिए कोई स्मृति आवंटन नहीं करता, लेकिन एक वस्तु के लिए यह जरूरी है।
एडी

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

@ पाओलो: मेरा एकमात्र बिंदु यह था कि इंटेगर परिमाण का एक क्रम है, फिर आदिम। और यह इस तथ्य के कारण है कि बॉक्सिंग प्रकार अपरिवर्तनीय हैं और हर बार आपके पास एक मूल्य बदलने के लिए एक नई वस्तु बनाई जाती है। मैंने दावा नहीं किया कि उनके साथ कुछ गलत है या तथ्य यह है कि वे अपरिवर्तनीय हैं। बस यह कि वे धीमे हैं और एक कोडर को यह जानना चाहिए। कैसे आदिम प्रकार के बिना ग्रूवी किराए पर एक नजर डालें jroller.com/rants/entry/why_is_groovy_so_slow
पीटर Knego

1
अपरिवर्तनीयता और ++यहाँ एक लाल हेरिंग है। कल्पना कीजिए कि जावा एक बहुत सरल तरीके से अधिक भार समर्थन ऑपरेटर के लिए बढ़ा दिया गया है, इस तरह अगर एक वर्ग (जैसे कि Integerएक विधि है plus, तो आप लिख सकते हैं i + 1के बजाय i.plus(1)। और यह भी मानते हैं कि संकलक स्मार्ट पर्याप्त विस्तार करने के लिए है i++में i = i + 1। अब आप कह सकते हैं i++और प्रभावी रूप से "परिवर्तनीय i" वृद्धि के बिना Integerपारस्परिक रूप से " ।
डैनियल इयरविकर

16

पहला और सबसे महत्वपूर्ण, आदत। यदि आपने आठ वर्षों के लिए जावा में कोडित किया है, तो आप काफी मात्रा में जड़ता जमा लेते हैं। यदि ऐसा करने के लिए कोई सम्मोहक कारण नहीं है तो परिवर्तन क्यों करें? ऐसा नहीं है कि बॉक्सिंग प्राइमेटिव का उपयोग करने से कोई अतिरिक्त लाभ होता है।

दूसरा कारण यह दावा करना है कि nullयह एक वैध विकल्प नहीं है। यह दो अंकों या पाश चर के योग के रूप में घोषित करने के लिए व्यर्थ और भ्रामक होगा Integer

इसका प्रदर्शन पहलू भी है, जबकि प्रदर्शन का अंतर कई मामलों में महत्वपूर्ण नहीं है (हालांकि जब यह है, तो यह बहुत बुरा है), कोई भी ऐसा कोड लिखना पसंद नहीं करता है जिसे आसानी से एक तेज़ तरीके से लिखा जा सके। अभ्यस्त।


15
मैं असहमत हूं। प्रदर्शन का पहलू महत्वपूर्ण हो सकता है। इसका बहुत कम हिस्सा शायद जड़ता या आदत का है।
एडी

7
@ ईदी यह हो सकता है, लेकिन यह बहुत कम है। मेरा विश्वास करो, ज्यादातर लोगों के लिए प्रदर्शन तर्क सिर्फ एक बहाना है।
biziclop

3
मैं भी प्रदर्शन तर्क की रक्षा करना चाहूंगा। डाल्विक के साथ एंड्रॉइड पर आपके द्वारा बनाई गई प्रत्येक ऑब्जेक्ट को जीसी के "जोखिम" में वृद्धि होगी और कहा जा सकता है कि आपके पास जितनी अधिक वस्तुएं हैं, वे लंबे समय तक रहेंगी। इसलिए लूप में इंट के बजाय इंटेगर बनाने से आपको कुछ गिराए गए फ्रेम की कीमत चुकानी पड़ेगी।
इगोर 35ordaš

1
@PSIXO यह एक उचित बिंदु है, मैंने इसे विशुद्ध रूप से सर्वर-साइड जावा को ध्यान में रखते हुए लिखा है। मोबाइल उपकरण एक अलग जानवर हैं। लेकिन मेरा कहना यह था कि यहां तक ​​कि डेवलपर्स जो अन्यथा प्रदर्शन के संबंध में बिना किसी भयानक कोड के लिखते हैं, यह एक कारण के रूप में उद्धृत करेगा, उनमें से यह एक बहाना के रूप में बहुत लगता है।
23

12

वैसे, स्मॉलटाक में केवल ऑब्जेक्ट्स (कोई आदिम नहीं) हैं, और फिर भी उन्होंने अपने छोटे पूर्णांक (सभी 32 बिट्स, केवल 27 या इस तरह का उपयोग करके) को किसी भी ढेर स्थान को आवंटित नहीं करने के लिए अनुकूलित किया था, लेकिन बस एक विशेष बिट पैटर्न का उपयोग करें। अन्य सामान्य वस्तुओं (सच्चे, झूठे, अशक्त) में भी विशेष बिट पैटर्न थे।

तो, कम से कम 64-बिट JVM (64 बिट पॉइंटर नेमस्पेस के साथ) पर यह संभव होना चाहिए कि इन्टर्गर, कैरेक्टर, बाइट, शॉर्ट, बुलियन, फ्लोट (और छोटा लॉन्ग) की कोई भी वस्तु (इनसे अलग नहीं) बनाई जाए। स्पष्ट रूप से new ...()), केवल विशेष बिट पैटर्न, जिसे सामान्य ऑपरेटरों द्वारा काफी कुशलता से हेरफेर किया जा सकता है।


मुझे "कुछ कार्यान्वयन" कहना चाहिए था, क्योंकि यह भाषा विनिर्देशों द्वारा शासित नहीं है, मुझे लगता है। (और दुख की बात है कि मैं यहां किसी भी स्रोत का हवाला नहीं दे सकता, यह केवल वही है जो मैंने कहीं सुना है।)
पाओलो एबरमैन

ŭlo, JIT पहले से ही सूचक में मेटा रखता है; incl, पॉइंटर GC जानकारी रख सकता है, या Klass (अनुकूलन वर्ग Integers को अनुकूलित करने की तुलना में बहुत बेहतर विचार है, जिसके लिए मैं कम देखभाल कर सकता हूं)। पॉइंटर बदलने के लिए प्रत्येक पॉइंटर लोड से पहले शिफ्ट / cmp / jnz कोड (या ऐसा कुछ) होना चाहिए। शाखा शायद हार्डवेयर द्वारा बहुत अच्छी तरह से भविष्यवाणी नहीं की जाएगी (क्योंकि यह मूल्य प्रकार और सामान्य वस्तु दोनों हो सकती है) और इससे प्रदर्शन हिट होगा।
बेस्टसेल्स

3
मैंने कुछ वर्षों तक स्मालटाक किया। अनुकूलन अभी भी बहुत महंगा था, एक इंट पर प्रत्येक ऑपरेशन के लिए उन्हें अनमास्क और उन्हें फिर से लागू करना था। वर्तमान में जावा आदिम संख्याओं में फेरबदल करते समय सी के बराबर है। अनमास्क + मास्क के साथ इसकी संभावना 30% धीमी होगी।
आर.ओलर

9

मैं विश्वास नहीं कर सकता कि किसी ने भी उल्लेख नहीं किया है कि मुझे क्या लगता है सबसे महत्वपूर्ण कारण है: "int" ऐसा है, "Integer" की तुलना में टाइप करना इतना आसान है। मुझे लगता है कि लोग संक्षिप्त वाक्य रचना के महत्व को कम आंकते हैं। प्रदर्शन वास्तव में उनसे बचने का एक कारण नहीं है, क्योंकि जब कोई नंबर का उपयोग कर रहा होता है, तो ज्यादातर लूप इंडेक्स में होता है, और उन लागतों की तुलना किसी भी गैर-तुच्छ लूप में नहीं करता है (चाहे आप इंट या इंटेगर का उपयोग कर रहे हों)।

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

दूसरा कारण यह था कि (नया लॉन्ग (1000)) == (नया लॉन्ग (1000)) गलत है, लेकिन यह कहने का एक और तरीका है कि "। असमान" में बॉक्स प्रकार के लिए कोई संक्रियात्मक समर्थन नहीं है (ऑपरेटरों के विपरीत <,> , =, आदि), इसलिए हम "सरल वाक्यविन्यास" कारण पर वापस आते हैं।

मुझे लगता है कि स्टीव येजेग का नॉन-प्रिमिटिव लूप उदाहरण मेरी बात को बहुत अच्छी तरह से दिखाता है: http://sites.google.com/site/steveyegge2/language-trickery-and-ejb

इस बारे में सोचें: आप कितनी बार उन भाषाओं में फ़ंक्शन प्रकारों का उपयोग करते हैं जिनमें उनके लिए अच्छा वाक्यविन्यास है (जैसे किसी भी कार्यात्मक भाषा, अजगर, रूबी और यहां तक ​​कि सी) जावा की तुलना में जहां आपको उन्हें रनवेबल और कॉलेबल जैसे इंटरफेस का उपयोग करके अनुकरण करना होगा बेनाम कक्षाएं।


8

प्राथमिकताओं से छुटकारा पाने के कारणों में से कुछ:

  • पीछे की संगतता।

यदि इसे समाप्त कर दिया जाता है, तो कोई भी पुराना कार्यक्रम भी नहीं चलेगा।

  • जेवीएम फिर से लिखना।

इस नई बात का समर्थन करने के लिए पूरे JVM को फिर से लिखना होगा।

  • बड़ी स्मृति पदचिह्न।

आपको मान और संदर्भ को संग्रहीत करने की आवश्यकता होगी, जो अधिक मेमोरी का उपयोग करता है। यदि आपके पास बाइट्स का एक विशाल सरणी है, तो byte's का उपयोग करने Byteकी तुलना में काफी छोटा है ।

  • अशक्त सूचक मुद्दे।

घोषणा करने के int iबाद सामान के साथ iकोई मुद्दा नहीं होगा, लेकिन घोषित करने Integer iऔर फिर एक ही करने के परिणामस्वरूप एक NPE होगा।

  • समानता के मुद्दे।

इस कोड पर विचार करें:

Integer i1 = 5;
Integer i2 = 5;

i1 == i2; // Currently would be false.

झूठा होगा। ऑपरेटरों को ओवरलोड करना होगा, और इसके परिणामस्वरूप सामान को फिर से लिखना होगा।

  • धीरे

ऑब्जेक्ट रैपर उनके आदिम समकक्षों की तुलना में काफी धीमा हैं।


i1 == i2; केवल i1> = 128 पर गलत होगा। तो, वर्तमान उदाहरण गलत है
Geniy

7

वस्तुएं आदिम प्रकारों की तुलना में बहुत अधिक भारी होती हैं, इसलिए आदिम प्रकार रैपर वर्गों के उदाहरणों की तुलना में बहुत अधिक कुशल होते हैं।

आदिम प्रकार बहुत सरल हैं: उदाहरण के लिए एक इंट 32 बिट्स है और स्मृति में बिल्कुल 32 बिट्स लेता है, और सीधे हेरफेर किया जा सकता है। इंटेगर ऑब्जेक्ट एक पूर्ण ऑब्जेक्ट है, जिसे (किसी भी ऑब्जेक्ट की तरह) को ढेर पर संग्रहीत किया जाना है, और इसे केवल एक संदर्भ (पॉइंटर) के माध्यम से एक्सेस किया जा सकता है। यह सबसे अधिक संभावना है कि मेमोरी के 32 से अधिक बिट्स (4 बाइट्स) भी लेता है।

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

उदाहरण के लिए, स्काला में कोई आदिम प्रकार नहीं हैं; पूर्णांकों के लिए एक वर्ग Int है, और एक Int एक वास्तविक ऑब्जेक्ट है (जो कि आप आदि को विधि कर सकते हैं)। जब कंपाइलर आपके कोड को संकलित करता है, तो यह दृश्यों के पीछे आदिम ints का उपयोग करता है, इसलिए एक int का उपयोग जावा में एक आदिम इंट का उपयोग करने के समान ही कुशल है।


1
मैंने यह मान लिया होगा कि JRE "स्मार्ट" होगा जो कि जावा लिपटे आदिम के साथ ऐसा करने के लिए पर्याप्त है। असफल।
Naftuli Kay

7

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


3
क्षमा करें, यह गलत है। एक स्मार्ट जेवीएम किसी भी ऑब्जेक्ट आवंटन पर विश्लेषण से बच सकता है और, यदि वे बच नहीं सकते हैं, तो उन्हें स्टैक पर आवंटित करें।
rlibby

2
हाँ, यह है शुरुआत आधुनिक JVMs की एक विशेषता किया जाना है। पांच वर्षों में, आप जो कहते हैं, वह अधिकांश जेवीएम के लिए सही होगा। आज ऐसा नहीं है। मैंने इस बारे में लगभग टिप्पणी की, लेकिन इस पर टिप्पणी नहीं करने का फैसला किया। शायद मुझे कुछ कहना चाहिए था।
एडी

6

आदिम प्रकार के कई फायदे हैं:

  • लिखने के लिए सरल कोड
  • प्रदर्शन बेहतर है क्योंकि आप चर के लिए ऑब्जेक्ट को तुरंत नहीं दे रहे हैं
  • चूंकि वे किसी वस्तु के संदर्भ का प्रतिनिधित्व नहीं करते हैं, इसलिए नल की जांच करने की कोई आवश्यकता नहीं है
  • जब तक आपको बॉक्सिंग सुविधाओं का लाभ उठाने की आवश्यकता न हो, तब आदिम प्रकारों का उपयोग करें।

5

यह जानना मुश्किल है कि कवर के तहत किस तरह के अनुकूलन हो रहे हैं।

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

हालाँकि, आदिमों के सरणियाँ स्पष्ट रूप से बॉक्सिंग आदिमों के संग्रह से बहुत अलग हैं । यह समझ में आता है कि एक संग्रह के भीतर बहुत कम अनुकूलन संभव हैं।

इसके अलावा, Integerइसकी तुलना में बहुत अधिक तार्किक ओवरहेड हैint : अब आपको इस बारे में चिंता करनी होगी कि int a = b + c;कोई अपवाद फेंकता है या नहीं ।

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


5
int loops = 100000000;

long start = System.currentTimeMillis();
for (Long l = new Long(0); l<loops;l++) {
    //System.out.println("Long: "+l);
}
System.out.println("Milliseconds taken to loop '"+loops+"' times around Long: "+ (System.currentTimeMillis()- start));

start = System.currentTimeMillis();
for (long l = 0; l<loops;l++) {
    //System.out.println("long: "+l);
}
System.out.println("Milliseconds taken to loop '"+loops+"' times around long: "+ (System.currentTimeMillis()- start));

मिलिसेकंड्स को लूप के चारों ओर '100000000' बार लूप: 468 लिया गया

मिलिसेकंड्स को लूप '100000000' के आसपास लंबे समय तक ले जाया गया: 31

एक साइड नोट पर, मुझे यह देखकर कुछ बुरा नहीं लगेगा कि यह जावा में है।

Integer loop1 = new Integer(0);
for (loop1.lessThan(1000)) {
   ...
}

जहां लूप के लिए स्वचालित रूप से लूप 1 को 0 से 1000 तक बढ़ाया जाता है या

Integer loop1 = new Integer(1000);
for (loop1.greaterThan(0)) {
   ...
}

जहां लूप के लिए स्वचालित रूप से लूप 1 1000 1000 से घट जाता है।


2
  1. गणितीय कार्य करने के लिए आपको प्राथमिकताओं की आवश्यकता होती है
  2. ऊपर बताए गए और बेहतर प्रदर्शन के रूप में आदिम कम स्मृति लेते हैं

आपको पूछना चाहिए कि क्लास / ऑब्जेक्ट प्रकार की आवश्यकता क्यों है

जब हम संग्रह से निपटते हैं, तो ऑब्जेक्ट प्रकार होने का कारण हमारे जीवन को आसान बनाना है। प्रिमिटिव्स को सीधे लिस्ट / मैप में नहीं जोड़ा जा सकता है, बल्कि आपको एक रैपर क्लास लिखने की जरूरत है। रेडीमेड इंटेगर की तरह की कक्षाएं आपको यहां मदद करती हैं और इसके साथ कई उपयोगिता विधियां भी हैं जैसे कि इंटेगर.परसेइंट (स्ट्र)


2

मैं पिछले उत्तरों से सहमत हूं, आदिम आवरण वस्तुओं का उपयोग करना महंगा हो सकता है। लेकिन, यदि आपके एप्लिकेशन में प्रदर्शन महत्वपूर्ण नहीं है, तो आप ऑब्जेक्ट का उपयोग करते समय ओवरफ्लो से बचते हैं। उदाहरण के लिए:

long bigNumber = Integer.MAX_VALUE + 2;

bigNumber-2147483647 का मूल्य है, और आप इसे 2147483649 होने की उम्मीद करेंगे। यह कोड में एक बग है जिसे करने से तय हो जाएगा:

long bigNumber = Integer.MAX_VALUE + 2l; // note that '2' is a long now (it is '2L').

और bigNumber2147483649 होगा। इस प्रकार के कीड़े कभी-कभी याद करने में आसान होते हैं और अज्ञात व्यवहार या कमजोरियों को जन्म दे सकते हैं (देखें CWE-190 )।

यदि आप रैपर ऑब्जेक्ट का उपयोग करते हैं, तो समतुल्य कोड संकलित नहीं होगा।

Long bigNumber = Integer.MAX_VALUE + 2; // Not compiling

इसलिए आदिम आवरण वस्तुओं का उपयोग करके इस तरह के मुद्दों को रोकना आसान है।

आपके प्रश्न का पहले से ही उत्तर दिया गया है, इसलिए मैं उत्तर देता हूं कि पहले थोड़ा और जानकारी जोड़ने के लिए पहले उल्लेख नहीं किया गया है।


1

क्योंकि JAVA आदिम प्रकार के सभी गणितीय कार्य करता है। इस उदाहरण पर विचार करें:

public static int sumEven(List<Integer> li) {
    int sum = 0;
    for (Integer i: li)
        if (i % 2 == 0)
            sum += i;
        return sum;
}

यहां, इंटीजर (संदर्भ) प्रकार पर रिमाइंडर और यूनीरी प्लस संचालन लागू नहीं किया जा सकता है, कंपाइलर अनबॉक्सिंग करता है और संचालन करता है।

तो, सुनिश्चित करें कि जावा प्रोग्राम में कितने ऑटोबॉक्सिंग और अनबॉक्सिंग ऑपरेशन होते हैं। चूंकि, इस ऑपरेशन को करने में समय लगता है।

आम तौर पर, प्रकार के संदर्भ और आदिम प्रकार के परिणाम के तर्क रखना बेहतर होता है।


1

आदिम प्रकार हैं बहुत तेजी से और भी बहुत आवश्यकता होती है कम स्मृति । इसलिए, हम उनका उपयोग करना पसंद कर सकते हैं।

दूसरी ओर, वर्तमान जावा भाषा विनिर्देशन जावा संग्रह या परावर्तन एपीआई में पैरामीटराइज्ड प्रकार (जेनरिक) में आदिम प्रकार के उपयोग की अनुमति नहीं देता है।

जब हमारे एप्लिकेशन को बड़ी संख्या में तत्वों के साथ संग्रह की आवश्यकता होती है, तो हमें यथासंभव "किफायती" प्रकार के साथ सरणियों का उपयोग करने पर विचार करना चाहिए।

* विस्तृत जानकारी के लिए स्रोत देखें: https://www.baeldung.com/java-primatics-vs-objects


0

संक्षिप्त होने के लिए: आदिम प्रकार तेज होते हैं और बॉक्सिंग की तुलना में कम स्मृति की आवश्यकता होती है

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.