जावा एनम सदस्यों की तुलना: == या बराबर ()?


1735

मुझे पता है कि जावा एनम निजी बिल्डरों और सार्वजनिक स्थैतिक सदस्यों के एक समूह के साथ संकलित हैं। किसी दिए गए एनम के दो सदस्यों की तुलना करते समय, मैंने हमेशा उपयोग किया है .equals(), जैसे

public useEnums(SomeEnum a)
{
    if(a.equals(SomeEnum.SOME_ENUM_VALUE))
    {
        ...
    }
    ...
}

हालाँकि, मैं अभी कुछ कोड भर आया हूँ ==जो असमानों () के बजाय बराबर ऑपरेटर का उपयोग करता है :

public useEnums2(SomeEnum a)
{
    if(a == SomeEnum.SOME_ENUM_VALUE)
    {
        ...
    }
    ...
}

मैं कौन सा ऑपरेटर उपयोग कर रहा हूं?


7
मैं बस एक बहुत ही इसी तरह के सवाल पर ठोकर खाई: stackoverflow.com/questions/533922/…
मैट बॉल

39
मुझे आश्चर्य है कि सभी उत्तरों में (विशेष रूप से पॉलीजेनबेलिकेंट से एक है जो विस्तार से बताता है कि क्यों == काम करता है) कि == का एक और बड़ा लाभ का उल्लेख नहीं किया गया था: यह स्पष्ट करता है कि कैसे एनम काम करते हैं (सिंगलटन के एक निश्चित सेट के रूप में) वस्तुओं)। बराबरी के साथ यह सोचने के लिए प्रेरित करता है कि किसी भी तरह एक ही enum 'वैकल्पिक' के कई उदाहरण हो सकते हैं।
स्टुअर्ट रॉसिटर

6
इसे सरल रखें। "==" अधिक पठनीय है और यह काम करता है क्योंकि एनाम डिफ़ॉल्ट रूप से सिंगलटन हैं। रेफ
लोकेश

जवाबों:


1574

दोनों तकनीकी रूप से सही हैं। यदि आप के लिए स्रोत कोड को देखते हैं .equals(), यह बस के लिए ख़ारिज करता है ==

==हालाँकि, मैं उपयोग करता हूँ , क्योंकि यह सुरक्षित रहेगा।


64
व्यक्तिगत रूप से, मुझे 'null सुरक्षा' पसंद नहीं है।
निवाज

257
@ निवास: क्यों नहीं? क्या आपको अपने तर्कों के क्रम के बारे में चिंता करना पसंद है (जो केवल पास्कल के उत्तर में, बायीं ओर से स्थिरांक की तुलना पर लागू होता है)? क्या आप हमेशा यह जाँचना पसंद करते हैं कि .equals()आईएनजी के पहले कोई वैल्यू शून्य नहीं है? मुझे पता है कि मैं नहीं।
मैट बॉल

86
ध्यान रखें कि जब आपका कोड पढ़ा जाता है, तो "==" तब तक पाठक को गलत दिखाई दे सकता है जब तक कि वह रवाना नहीं हो जाता है और इसमें शामिल प्रकार के स्रोत को देखता है, फिर देखता है कि यह एक एनम है। इस अर्थ में, यह ".equals ()" को पढ़ने के लिए कम विचलित करने वाला है।
केविन बोर्रिलियन

60
@ केविन - यदि आप एक आईडीई का उपयोग नहीं कर रहे हैं जो आपको स्रोत को देखते हुए सीधे प्रकार देखने की अनुमति देता है, तो आप खुद को धोखा दे रहे हैं - एक उचित आईडीई के साथ कोई समस्या नहीं।
MetroidFan2002

63
कभी-कभी कोड फिर से सक्रिय हो जाता है और यह संभव है कि एक एनम को एक वर्ग द्वारा प्रतिस्थापित किया जाता है, जिस बिंदु पर == अब सही होने की गारंटी नहीं है, जबकि समान रूप से काम करना जारी है। इस कारण से, बराबरी स्पष्ट रूप से एक बेहतर विकल्प है। यदि आप अशक्त सुरक्षा चाहते हैं (क्योंकि आप एक कोड आधार पर काम करते हैं जो नल के उपयोग को कम करने के लिए नहीं लिखा गया था), तो वहाँ अपाचे ऑब्जेक्टयूलेट्स या अमरूद की वस्तुएं # बराबर हैं (या आप अपना रोल कर सकते हैं)। मैं डर के लिए "प्रदर्शन" शब्द का भी उल्लेख नहीं करूंगा कि कोई मुझे डोनाल्ड नथ पुस्तक के साथ सही थप्पड़ मारे।
लेज़लोक

1113

==पर इस्तेमाल किया जा सकता है enum?

हां: enums में तंग उदाहरण नियंत्रण हैं जो आपको ==उदाहरणों की तुलना करने के लिए उपयोग करने की अनुमति देता है । यहाँ भाषा विनिर्देश द्वारा प्रदान की गई गारंटी (मेरे द्वारा जोर):

जेएलएस 8.9 एनम

एक एनुम प्रकार का कोई अन्य उदाहरण नहीं है, जो इसके एनम स्थिरांक द्वारा परिभाषित है।

यह स्पष्ट रूप से एक एनम प्रकार को तुरंत करने का प्रयास करने के लिए एक संकलन-समय की त्रुटि है। यह सुनिश्चित final cloneकरने की विधि Enumकि enumस्थिरांक को कभी भी क्लोन नहीं किया जा सकता है, और क्रमांकन तंत्र द्वारा विशेष उपचार यह सुनिश्चित करता है कि डुप्लिकेट इंस्टेंसेस को कभी-कभी डीरियलाइजेशन के परिणामस्वरूप नहीं बनाया जाता है। Enum प्रकार के चिंतनशील तात्कालिकता निषिद्ध है। साथ में, ये चार चीजें सुनिश्चित करती हैं कि स्थिरांक enumद्वारा परिभाषित लोगों से परे किसी प्रकार का कोई उदाहरण मौजूद नहीं है enum

क्योंकि प्रत्येक enumस्थिरांक का केवल एक ही उदाहरण है , दो विधि संदर्भों की तुलना करते समय विधि के स्थान पर ऑपरेटर का उपयोग करने की अनुमति है यदि यह ज्ञात हो कि उनमें से कम से कम एक स्थिरांक को संदर्भित करता है==equalsenum । ( equalsविधि Enumएक ऐसी finalविधि है जो केवल super.equalsअपने तर्क पर आक्रमण करती है और परिणाम लौटाती है, इस प्रकार एक पहचान तुलना का प्रदर्शन करती है।)

यह गारंटी काफी मजबूत है कि जोश बलोच ने सिफारिश की है कि यदि आप सिंगलटन पैटर्न का उपयोग करने पर जोर देते हैं, तो इसे लागू करने का सबसे अच्छा तरीका एक तत्व का उपयोग करना है enum(देखें: प्रभावी जावा 2 संस्करण, आइटम 3: एकल के साथ सिंगलटन संपत्ति को लागू करें निजी कंस्ट्रक्टर या एक एनुम प्रकार ; सिंगलटन में थ्रेड सुरक्षा )


==और के बीच अंतर क्या हैं equals?

एक अनुस्मारक के रूप में, यह कहा जाना चाहिए कि आम तौर पर, ==एक व्यवहार्य विकल्प नहीं है equals। हालांकि, यह (जैसे कि साथ enum) है, पर विचार करने के लिए दो महत्वपूर्ण अंतर हैं:

== कभी नहीं फेंकता NullPointerException

enum Color { BLACK, WHITE };

Color nothing = null;
if (nothing == Color.BLACK);      // runs fine
if (nothing.equals(Color.BLACK)); // throws NullPointerException

== संकलन समय पर अनुकूलता जाँच के अधीन है

enum Color { BLACK, WHITE };
enum Chiral { LEFT, RIGHT };

if (Color.BLACK.equals(Chiral.LEFT)); // compiles fine
if (Color.BLACK == Chiral.LEFT);      // DOESN'T COMPILE!!! Incompatible types!

==लागू होने पर उपयोग किया जाना चाहिए?

बलोच ने विशेष रूप से उल्लेख किया है कि अपरिवर्तनीय वर्ग जिनके पास अपने उदाहरणों पर उचित नियंत्रण है, वे अपने ग्राहकों के लिए गारंटी दे सकते हैं जो ==उपयोग करने योग्य है। enumविशेष रूप से उदाहरण के लिए उल्लेख किया गया है।

आइटम 1: कंस्ट्रक्टरों के बजाय स्थैतिक कारखाने के तरीकों पर विचार करें

[...] यह एक अपरिवर्तनीय वर्ग को यह सुनिश्चित करने की अनुमति देता है कि कोई दो समान उदाहरण मौजूद नहीं हैं: a.equals(b)यदि और केवल यदि a==b। यदि कोई वर्ग यह गारंटी देता है, तो उसके ग्राहक विधि के ==बजाय ऑपरेटर का उपयोग कर सकते हैं equals(Object), जिसके परिणामस्वरूप बेहतर प्रदर्शन हो सकता है। Enum प्रकार यह गारंटी प्रदान करते हैं।

संक्षेप में, का उपयोग ==करने के लिए तर्क enumहैं:

  • यह काम करता हैं।
  • यह तेज है।
  • यह रन-टाइम पर अधिक सुरक्षित है।
  • यह संकलन-समय पर अधिक सुरक्षित है।

27
अच्छा जवाब लेकिन ... 1. यह काम करता है : सहमत 2. यह तेजी से है : इसे एनमों के लिए साबित करें :) 3. यह रन-टाइम पर अधिक सुरक्षित है : Color nothing = null;IMHO एक बग है और इसे ठीक किया जाना चाहिए, आपके एनम में दो मान हैं, तीन नहीं ( टॉम हैटिन की टिप्पणी देखें) 4. यह संकलन-समय पर सुरक्षित है : ठीक है, लेकिन equalsफिर भी वापस आ जाएगा false। अंत में, मैं इसे नहीं खरीदता, मैं equals()पठनीयता के लिए पसंद करता हूं (केविन की टिप्पणी देखें)।
पास्कल थिवेंट

201
यह जावा के खिलाफ एक काला निशान है जो कुछ लोगों को लगता है कि इससे foo.equals(bar)अधिक पठनीय हैfoo == bar
बेनेट मैकलेवे

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

35
"यदि आपके प्रोग्रामर कितने विनम्र हैं, तो" सुरक्षित "वह चीज़ है जो आप नहीं हैं।" - मैं इस उद्धरण से सहमत नहीं हूं। यह सभी प्रकार की जाँच है: संकलन समय पर "गूंगा" गलतियों को रोकना, इस प्रकार कोड चलने से पहले भी। यहां तक ​​कि स्मार्ट लोग भी गलतियां करते हैं, वादों की तुलना में बेहतर गारंटी देता है।
यमजोरोस

7
@ इलाज़लोक: यकीन है, लेकिन अगर चीजें विफल हो सकती हैं, तो वे बस करेंगे। कुछ गूंगी गलतियों के लिए एक बाड़ होना हमेशा एक अच्छी बात है। कम तुच्छ कीड़े के लिए रचनात्मक होने के लिए बहुत जगह है, कंपाइलर को अपने कोड को चलाने का प्रयास करने से पहले इसे संभाल लें।
यमजोरोस

88

==दो enum मानों की तुलना करने के लिए उपयोग करना काम करता है, क्योंकि प्रत्येक enum स्थिरांक के लिए केवल एक ही वस्तु है।

एक साइड नोट पर, वास्तव में ==अशक्त-सुरक्षित कोड लिखने के लिए उपयोग करने की आवश्यकता नहीं है , यदि आप equals()इस तरह लिखते हैं :

public useEnums(final SomeEnum a) {
    if (SomeEnum.SOME_ENUM_VALUE.equals(a)) {
        
    }
    
}

यह एक सबसे अच्छा अभ्यास है जिसे कॉन्सटेंट से द लेफ्ट की तुलना के रूप में जाना जाता है जिसे आपको निश्चित रूप से पालन करना चाहिए।


9
मैं यह तब करता हूं जब .equals()स्ट्रिंग मानों को निगला जाता है, लेकिन मुझे अभी भी लगता है कि यह अशक्त-सुरक्षित कोड लिखने का एक भद्दा तरीका है। मेरे पास एक ऑपरेटर (या एक विधि) है, लेकिन मुझे पता है कि [अशक्त वस्तु]। असमानता जावा में कभी भी अशक्त नहीं होगी क्योंकि डॉट ऑपरेटर कैसे काम करता है) जो हमेशा शून्य-सुरक्षित होता है, भले ही वह कितना भी सुरक्षित क्यों न हो। आदेश में इसका उपयोग किया जाता है। शब्दार्थ, "बराबर" ऑपरेटर को हमेशा कम्यूट करना चाहिए ।
मैट बॉल

2
खैर, जैसा कि जावा में ग्रूवी ( ?.) का सेफ नेविगेशन ऑपरेटर नहीं है , मैं इस अभ्यास का उपयोग तब करना जारी रखूंगा जब स्थिरांक और टीबीएच की तुलना में, मुझे यह भद्दा नहीं लगता, शायद कम "प्राकृतिक"।
पास्कल थिवेंट

32
एक nullएनम आमतौर पर एक त्रुटि है। आपको सभी संभावित मूल्यों का यह ज्ञान प्राप्त है, और यहाँ एक और एक है!
टॉम हॉल्टिन -

8
स्पष्ट रूप से एनोटेट किए गए मानों को छोड़कर @Nullable, मैं वामपंथियों से कांस्टेंट की तुलना को एक एंटीपैर्टेंट मानता हूं क्योंकि यह अस्पष्टता फैलाता है कि कौन से मूल्य शून्य हो सकते हैं या नहीं। एनम प्रकार लगभग कभी नहीं होना चाहिए @Nullable, इसलिए एक शून्य मान एक प्रोग्रामिंग त्रुटि होगी; ऐसे मामले में, जितनी जल्दी आप एनपीई को फेंकते हैं, उतनी ही अधिक संभावना है कि आप अपनी प्रोग्रामिंग गलती पाएंगे जहां आपने इसे शून्य होने की अनुमति दी थी। तो "सबसे अच्छा अभ्यास ... जो आपको निश्चित रूप से पालन करना चाहिए" जब यह फिटकिरी के प्रकार की बात आती है तो यह गलत है।
टोबियास

24
वामपंथियों से कांस्टेंट की तुलना करें तो सबसे अच्छी प्रथा योडा शैली की सबसे अच्छी अंग्रेजी है।
मातरिनस

58

के रूप में अन्य लोगों ने कहा, दोनों ==और .equals()ज्यादातर मामलों में काम करते हैं। संकलन समय निश्चितता, जिसकी आप पूरी तरह से विभिन्न प्रकार की वस्तुओं की तुलना नहीं कर रहे हैं, जो अन्य लोगों ने बताई हैं, मान्य और लाभदायक हैं, हालांकि दो अलग-अलग संकलन समय प्रकारों की वस्तुओं की तुलना करने का विशेष प्रकार भी FindBugs द्वारा पाया जाएगा (और शायद द्वारा ग्रहण / IntelliJ समय निरीक्षण का संकलन करता है), इसलिए जावा संकलक यह पता लगाता है कि इसमें अतिरिक्त सुरक्षा नहीं है।

तथापि:

  1. यह तथ्य कि ==मेरे दिमाग में कभी भी एनपीई नहीं फेंकता है, इसका एक नुकसान है ==। किसी भी अतिरिक्त स्थिति के लिए शायद ही कभी किसी enumप्रकार की आवश्यकता होनी चाहिए null, क्योंकि आप जिस अतिरिक्त स्थिति के माध्यम से व्यक्त करना चाहते हैं nullउसे केवल enumएक अतिरिक्त उदाहरण के रूप में जोड़ा जा सकता है । यदि यह अप्रत्याशित रूप से है null, तो मेरे पास ==चुपचाप झूठे का मूल्यांकन करने की तुलना में एक एनपीई है । इसलिए मैं रन-टाइम राय में इसके साथ असहमत हूं ; enumमूल्यों को कभी भी आड़े न आने देना बेहतर है @Nullable
  2. तर्क यह है कि ==है तेजी से भी फर्जी है। ज्यादातर मामलों में आप .equals()एक वैरिएबल पर कॉल करेंगे जिसका संकलन समय प्रकार एनम वर्ग है, और उन मामलों में कंपाइलर जान सकता है कि यह उसी तरह है ==(क्योंकि एक enum's equals()विधि को ओवरराइड नहीं किया जा सकता) और फ़ंक्शन कॉल को अनुकूलित कर सकता है। दूर। मुझे यकीन नहीं है कि कंपाइलर वर्तमान में ऐसा करता है, लेकिन अगर ऐसा नहीं होता है, और कुल मिलाकर जावा में प्रदर्शन की समस्या है, तो मैं संकलक को ठीक कर दूंगा कि 100,000 से अधिक जावा प्रोग्रामर सूट करने के लिए अपनी प्रोग्रामिंग शैली को बदल दें। एक विशेष संकलक संस्करण की प्रदर्शन विशेषताएँ।
  3. enumsवस्तुएं हैं। अन्य सभी प्रकारों के लिए मानक तुलना है .equals(), नहीं ==। मुझे लगता है कि इसके लिए एक अपवाद बनाना खतरनाक है enumsक्योंकि आप गलती से वस्तुओं की तुलना ==करने की बजाय समाप्त कर सकते हैं equals(), खासकर यदि आप enumएक गैर-एनम वर्ग में रिफ्लेक्टर करते हैं। इस तरह के रिफैक्टरिंग के मामले में, यह ऊपर से काम करता है, गलत है। अपने आप को यह समझाने के लिए कि इसका उपयोग ==सही है, आपको यह जांचने की आवश्यकता है कि क्या प्रश्न में मूल्य या तो एक है enumया एक आदिम है; यदि यह एक गैर- enumवर्ग था, तो यह गलत होगा लेकिन याद रखना आसान होगा क्योंकि कोड अभी भी संकलित होगा। एक ही मामला है जब का उपयोग करें.equals()गलत होगा यदि प्रश्न में मूल्य आदिम थे; उस स्थिति में, कोड संकलित नहीं होगा, इसलिए इसे याद करना बहुत कठिन है। इसलिए, .equals()सही के रूप में पहचानना बहुत आसान है, और भविष्य के रिफैक्टरिंग के खिलाफ सुरक्षित है।

मुझे वास्तव में लगता है कि जावा लैंग्वेज को =। लेफ्ट हैंड वैल्यू पर कॉल (।) करने के लिए वस्तुओं पर == को परिभाषित करना चाहिए, और ऑब्जेक्ट आइडेंटिटी के लिए एक अलग ऑपरेटर की शुरुआत करनी चाहिए, लेकिन ऐसा नहीं है कि जावा को कैसे परिभाषित किया गया।

संक्षेप में, मुझे अभी भी लगता तर्कों का उपयोग के पक्ष में हैं .equals()के लिए enumप्रकार के।


4
खैर, बिंदु 3 के बारे में, मैं enumएक switchलक्ष्य के रूप में उपयोग कर सकता हूं ताकि वे थोड़ा विशेष हो। Strings थोड़ा खास भी हैं।
कर्टनडॉग

स्विच स्टेटमेंट के लिए वाक्यविन्यास में न तो == और न ही। असमान () शामिल हैं, इसलिए मैं नहीं देखता कि आपकी बात क्या है। मेरी बात 3.) एक पाठक के लिए सत्यापित करना कितना आसान कोड है। जब तक स्विच स्टेटमेंट संकलित होता है तब तक स्विच स्टेटमेंट की समानता शब्दार्थक सही होती हैं।
तोबियास

17

मैं ==इसके बजाय उपयोग करना पसंद करता हूं equals:

अन्य कारण, यहां पहले से ही चर्चा किए गए अन्य लोगों के अलावा, क्या आप इसे महसूस किए बिना बग का परिचय दे सकते हैं। मान लीजिए कि आपके पास यह एनम है जो बिल्कुल वैसा ही है, लेकिन अलग-अलग pacakges में (यह आम नहीं है, लेकिन ऐसा हो सकता है):

पहला एनम :

package first.pckg

public enum Category {
    JAZZ,
    ROCK,
    POP,
    POP_ROCK
}

दूसरी गणना:

package second.pckg

public enum Category {
    JAZZ,
    ROCK,
    POP,
    POP_ROCK
}

फिर मान लीजिए कि आप अगले जैसे बराबरी का उपयोग करते हैं item.category, first.pckg.Categoryलेकिन आप दूसरे एनम ( second.pckg.Category) को आयात करते हैं, बजाय इसके कि इसे साकार किए बिना:

import second.pckg.Category;
...

Category.JAZZ.equals(item.getCategory())

तो आप allways मिल जाएगा falseएक अलग enum है कारण हालांकि जैसा कि आप उम्मीद सच है क्योंकि item.getCategory()है JAZZ। और इसे देखना थोड़ा मुश्किल हो सकता है।

इसलिए, यदि आप इसके बजाय ऑपरेटर का उपयोग करते हैं तो आपके ==पास एक संकलन त्रुटि होगी:

ऑपरेटर == को "second.pckg.Category", "first.pckg.Category" पर लागू नहीं किया जा सकता

import second.pckg.Category; 
...

Category.JAZZ == item.getCategory() 

बहुत अच्छे बिंदुओं का आपने उल्लेख किया। तो मैं क्या करना होगा myenum.value () और फिर == तुलना NPE सुरक्षा के लिए करना है।
जावा मेन

14

यहाँ दो की तुलना करने के लिए एक कच्चे समय परीक्षण है:

import java.util.Date;

public class EnumCompareSpeedTest {

    static enum TestEnum {ONE, TWO, THREE }

    public static void main(String [] args) {

        Date before = new Date();
        int c = 0;

        for(int y=0;y<5;++y) {
            for(int x=0;x<Integer.MAX_VALUE;++x) {
                if(TestEnum.ONE.equals(TestEnum.TWO)) {++c;}
                if(TestEnum.ONE == TestEnum.TWO){++c;}              
            }
        }

        System.out.println(new Date().getTime() - before.getTime());
    }   

}

एक बार में IFs पर टिप्पणी करें। यहाँ दो अलग-अलग बाइट-कोड में ऊपर से तुलना की गई है:

 21  getstatic EnumCompareSpeedTest$TestEnum.ONE : EnumCompareSpeedTest.TestEnum [19]
 24  getstatic EnumCompareSpeedTest$TestEnum.TWO : EnumCompareSpeedTest.TestEnum [25]
 27  invokevirtual EnumCompareSpeedTest$TestEnum.equals(java.lang.Object) : boolean [28]
 30  ifeq 36

 36  getstatic EnumCompareSpeedTest$TestEnum.ONE : EnumCompareSpeedTest.TestEnum [19]
 39  getstatic EnumCompareSpeedTest$TestEnum.TWO : EnumCompareSpeedTest.TestEnum [25]
 42  if_acmpne 48

पहला (बराबर) एक आभासी कॉल करता है और स्टैक से रिटर्न बूलियन का परीक्षण करता है। दूसरा (==) स्टैक से सीधे ऑब्जेक्ट पतों की तुलना करता है। पहले मामले में अधिक गतिविधि है।

मैंने एक बार में दोनों IFs के साथ कई बार यह परीक्षण चलाया। "==" कभी इतना तेज होता है।


मुझे संदेह है कि संकलक शाखा-भविष्यवाणी इस परीक्षण को अमान्य बना सकती है। एक स्मार्ट कंपाइलर यह पहचानता है कि दोनों यदि कथन हमेशा गलत का मूल्यांकन करेंगे और इस प्रकार कई तुलना करने से बचेंगे। वास्तव में एक स्मार्ट कंपाइलर यह भी पहचान सकता है कि y और x छोरों के मानों का परिणाम पर कोई प्रभाव नहीं पड़ेगा और पूरी चीज को अनुकूलित कर देगा ...
Darrel Hoffman

यह हो सकता है, लेकिन यह निश्चित रूप से नहीं करता है। मैं अपने उत्तर में वास्तविक संकलक द्वारा निर्मित बायटेकोड दिखाता हूं।
क्रिसकंट्रेल

तुम दोनों भ्रमित हो। :-) शाखा भविष्यवाणी रन-टाइम पर काम करती है इसलिए अलग बाइट कोड सुपर प्रासंगिक नहीं है। हालांकि, इस मामले में शाखा की भविष्यवाणी दोनों मामलों को समान रूप से मदद करेगी ।
vidstige

7
किसे पड़ी है? जब तक आप एक वीडियो गेम के दौरान एक लूप के अंदर हजारों बार एनम की तुलना कर रहे हैं, तब तक अतिरिक्त नैनोसेकंड व्यर्थ है।
user949300

जब तक आप व्याख्या किए गए मोड के लिए बाध्य नहीं करते तब तक प्रदर्शन के लिए बाइटेकोड बहुत अप्रासंगिक है। JMH बेंचमार्क यह देखने के लिए लिखें कि प्रदर्शन बिल्कुल समान है।
Maaartinus


7

tl; डॉ

एक अन्य विकल्प Objects.equalsउपयोगिता विधि है।

Objects.equals( thisEnum , thatEnum )

Objects.equals अशक्त-सुरक्षा के लिए

बराबर ऑपरेटर == के बजाय। असमान ()

मैं कौन सा ऑपरेटर उपयोग कर रहा हूं?

एक तीसरा विकल्प जावा 7 और बाद में जोड़े गए उपयोगिता वर्ग equalsपर पाया जाने वाला स्थिर तरीका है ।Objects

उदाहरण

यहां Monthएनम का उपयोग करके एक उदाहरण दिया गया है ।

boolean areEqual = Objects.equals( Month.FEBRUARY , Month.JUNE ) ;  // Returns `false`.

लाभ

मुझे इस विधि से कुछ लाभ मिले:

  • अशक्त-सुरक्षा
    • दोनों अशक्त ➙ true
    • या तो नल ➙ false
    • फेंकने का कोई खतरा नहीं NullPointerException
  • कॉम्पैक्ट, पठनीय

यह काम किस प्रकार करता है

तर्क किसके द्वारा प्रयोग किया जाता है Objects.equals?

खुद के लिए देखें, से जावा 10 स्रोत कोड की OpenJDK :

return (a == b) || (a != null && a.equals(b));

6

==एनम स्थिरांक की तुलना करने के अलावा किसी भी चीज़ का उपयोग करना बकवास है। यह वस्तुओं की तुलना करनेclassequals जैसा है - ऐसा मत करो!

हालाँकि, सन JDK 6u10 में एक बुरा बग (BugId 6277781 ) और इससे पहले ऐतिहासिक कारणों से दिलचस्प हो सकता है। इस बग ने ==deserialized enums पर उचित उपयोग को रोका , हालांकि यह यकीनन एक कोने के मामले में कुछ हद तक है।


4

Enums वे वर्ग हैं जो (इम्यूटेबल) द्वारा घोषित प्रत्येक गणन स्थिरांक के लिए एक उदाहरण (एकल की तरह) लौटाते हैं, public static final fieldताकि ==ऑपरेटर equals()विधि का उपयोग करने के बजाय उनकी समानता की जांच करने के लिए इस्तेमाल किया जा सके


1

Enums आसानी से == के साथ काम करते हैं क्योंकि प्रत्येक परिभाषित उदाहरण एक सिंगलटन भी है। तो == का उपयोग करके पहचान की तुलना हमेशा काम करेगी।

लेकिन == का उपयोग करते हुए क्योंकि यह एनम के साथ काम करता है इसका मतलब है कि आपके सभी कोड को उस एनम के उपयोग के साथ कसकर जोड़ा गया है।

उदाहरण के लिए: Enums एक इंटरफ़ेस लागू कर सकते हैं। मान लीजिए कि आप वर्तमान में एक Enum का उपयोग कर रहे हैं जो Interface1 को लागू करता है। यदि बाद में, कोई इसे बदलता है या समान इंटरफ़ेस के कार्यान्वयन के रूप में एक नया वर्ग Impl1 पेश करता है। फिर, यदि आप Impl1 के उदाहरणों का उपयोग करना शुरू करते हैं, तो आपके पास == के पिछले उपयोग के कारण बहुत सारे कोड बदलने और परीक्षण करने होंगे।

इसलिए, यह उचित है कि जब तक कोई उचित लाभ न हो, एक अच्छा अभ्यास समझा जाए।


अच्छा जवाब है, लेकिन पहले से ही यहाँ उल्लेख किया है
shmosel

उम। उस बिंदु पर, यह सवाल होगा कि आप इंटरफ़ेस पर == का उपयोग करते हैं या बराबर करते हैं। साथ ही सभी प्रकार के प्रश्नों के बारे में कि क्या यह एक समझदार कार्यान्वयन के साथ एक अपरिवर्तनीय प्रकार के कार्यान्वयन को बदलने के लिए वास्तव में समझदार है। और यह समझ लेना संभव है कि उचित लाभ के बारे में चिंता करने से पहले आपको क्या अच्छा अभ्यास करना है। (imho == बेहतर अभ्यास है)।
रॉबिन डेविस

1

सोनार नियमों में से एक है Enum values should be compared with "=="। कारण इस प्रकार हैं:

किसी एनम मूल्य के साथ समानता का परीक्षण equals()पूरी तरह से मान्य है क्योंकि एक एनम एक वस्तु है और प्रत्येक जावा डेवलपर को पता है ==कि इसका उपयोग किसी वस्तु की सामग्री की तुलना करने के लिए नहीं किया जाना चाहिए। उसी समय, ==एनमों पर प्रयोग करना:

  • के रूप में ही अपेक्षित तुलना (सामग्री) प्रदान करता है equals()

  • से अधिक अशक्त है equals()

  • रनटाइम जाँच के बजाय संकलन-समय (स्थैतिक) जाँच प्रदान करता है

इन कारणों से, के उपयोग को ==प्राथमिकता दी जानी चाहिए equals()

पिछले नहीं बल्कि कम से कम, ==पर enums यकीनन से अधिक पठनीय (कम क्रिया) है equals()


0

संक्षेप में, दोनों के पक्ष और विपक्ष हैं।

एक तरफ, इसका उपयोग करने के फायदे हैं ==, जैसा कि अन्य उत्तरों में वर्णित है।

दूसरी ओर, यदि आप किसी भी कारण से एनमों को एक अलग दृष्टिकोण (सामान्य वर्ग उदाहरण) से बदल देते हैं, ==तो आपको काटने का उपयोग किया जाता है । (BTDT।)


-1

मैं उत्तर देना चाहता हूं

मैं व्यक्तिगत रूप से बराबर () पसंद करता हूं। लेकिन यह झील के प्रकार की संगतता की जांच करता है। जो मुझे लगता है कि एक महत्वपूर्ण सीमा है।

संकलन समय पर टाइप संगतता की जाँच करने के लिए, घोषणा करें और अपने एनम में एक कस्टम फ़ंक्शन का उपयोग करें।

public boolean isEquals(enumVariable) // compare constant from left
public static boolean areEqual(enumVariable, enumVariable2) // compare two variable

इसके साथ, आपको दोनों समाधानों का लाभ मिला: NPE सुरक्षा, कोड को पढ़ने में आसान और संकलन समय पर संगतता की जांच।

मैं enum के लिए UNDEFINED मान जोड़ने की भी सलाह देता हूं।


4
यह समाधान किसी से बेहतर क्यों है ==? आपके साथ ==NPE सुरक्षा, आसानी से पढ़ा जाने वाला कोड, और समय टाइप कम्पैटिबिलिटी चेकिंग संकलित हो जाती है, और आप सभी को बिना किसी कस्टम-बराबरी के तरीके लिखने
मैट बॉल

1
एक UNDEFINEDमूल्य शायद एक अच्छा विचार है। बेशक, जावा 8 में आप Optionalइसके बजाय उपयोग करेंगे ।
टॉमस

-7

==फेंक सकते हैं NullPointerExceptionअगर एक आदिम प्रकार अपने वर्ग संस्करण की तुलना में किया जा रहा है। उदाहरण के लिए:

private static Integer getInteger() {
    return null;
}

private static void foo() {
    int a = 10;

    // Following comparison throws a NPE, it calls equals() on the 
    // non-primitive integer which is itself null. 
    if(a == getInteger()) { 
        // Some code
    }
}

2
इस प्रश्न पर गुंजाइश स्पष्ट है और आदिम प्रकार के दायरे में नहीं हैं।
टॉम

@ यहां चल रही चर्चा भ्रामक है जो ==कभी भी फेंक नहीं सकती NPEs। इस प्रश्न के पर्याप्त उत्तर हैं, लेकिन यह मेरे जैसे किसी व्यक्ति को बग / सुविधा प्राप्त करने में 2 घंटे लगने की स्थिति में यह एक अच्छा संदर्भ हो सकता है।
आयुषप

1
जब आप इस प्रश्न के विषय को अनदेखा नहीं करते हैं तो मैं एक NPE नहीं फेंक सकता। और यहां तक ​​कि अगर आप इस जवाब को यहां रखते हैं, तो क्या आपको लगता है कि किसी ने उसी मुद्दे के साथ जो आपको कुछ अलग खोज के द्वारा यह जवाब मिला होगा? उस व्यक्ति को उन एनमों की खोज करने की आवश्यकता होगी जो वे स्पष्ट रूप से उपयोग नहीं करते हैं। इस उत्तर से इस प्रश्न पर और अधिक प्रभाव पड़ेगा: stackoverflow.com/questions/7520432/…
टॉम
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.