जावा एनुम - नाम के बजाय स्ट्रिंग का उपयोग क्यों करें


171

यदि आप एनम एपी में देखते name()हैं कि यह किस विधि के अनुसार है:

इस एनम का नाम स्थिर रखता है, ठीक उसी तरह जैसे कि एनम अपनी घोषणा में घोषित करता है। अधिकांश प्रोग्रामर को पहले की तुलना में इस .String पद्धति का उपयोग करना चाहिए, क्योंकि String पद्धति अधिक उपयोगकर्ता-अनुकूल नाम वापस कर सकती है। यह विधि मुख्य रूप से विशिष्ट स्थितियों में उपयोग के लिए डिज़ाइन की गई है जहाँ शुद्धता सटीक नाम प्राप्त करने पर निर्भर करती है, जो रिलीज़ से रिलीज़ होने तक भिन्न नहीं होगी।

उपयोग करना बेहतर क्यों है toString()? मेरा मतलब है कि जब नाम () पहले से ही अंतिम हो तो स्ट्रिंग को ओवरराइड किया जा सकता है। इसलिए यदि आप स्ट्रींग का उपयोग करते हैं और कोई व्यक्ति हार्ड-कोडित मूल्य को वापस करने के लिए इसे ओवरराइड करता है तो आपका पूरा एप्लिकेशन डाउन हो जाता है ... इसके अलावा यदि आप सोर्सिंग में देखते हैं () विधि बिल्कुल और सिर्फ नाम वापस आती है। एक ही बात है।


4
आप toString()अपने एनम में ओवरराइड कर सकते हैं , लेकिन कोई और इसे बढ़ा और ओवरराइड नहीं कर सकता है। आप दुश्मनी नहीं बढ़ा सकते।
इरिक जी। हागस्ट्रॉम

जवाबों:


198

यह वास्तव में इस बात पर निर्भर करता है कि आप लौटे मूल्य के साथ क्या करना चाहते हैं:

  • यदि आपको एनम को स्थिर घोषित करने के लिए उपयोग किए जाने वाले सटीक नाम की आवश्यकता है, तो आपको उपयोग करना चाहिए name()जैसा toStringकि ओवरराइड हो सकता है
  • यदि आप यूजर फ्रेंडली तरीके से एनम को लगातार प्रिंट करना चाहते हैं, तो आपको इसका उपयोग करना चाहिए toStringजो कि ओवरराइड (या नहीं) हो सकता है।

जब मुझे लगता है कि यह भ्रामक हो सकता है, तो मैं getXXXउदाहरण के लिए एक अधिक विशिष्ट विधि प्रदान करता हूं :

public enum Fields {
    LAST_NAME("Last Name"), FIRST_NAME("First Name");

    private final String fieldDescription;

    private Fields(String value) {
        fieldDescription = value;
    }

    public String getFieldDescription() {
        return fieldDescription;
    }
}

1
यह स्वीकार्य है। यद्यपि अगर वे आधार वर्ग की चीजों को आसान बनाते हैं, तो उन्हें गणना करना आसान होगा।
राल्फगैब

55

का प्रयोग करें name()जब आप एक तुलना कर सकते हैं या अपने कोड में कुछ आंतरिक उपयोग के लिए हार्डकोडेड मान का उपयोग करना चाहते हैं।

का प्रयोग करें toString()जब आप किसी उपयोगकर्ता को वर्तमान जानकारी (एक developper एक लॉग को देख सहित) करना चाहते हैं। toString()एक विशिष्ट मूल्य देने पर कभी भी अपने कोड पर भरोसा न करें । एक विशिष्ट स्ट्रिंग के खिलाफ कभी भी इसका परीक्षण न करें। यदि आपका कोड तब टूटता है जब कोई सही तरीके से toString()रिटर्न बदलता है , तो यह पहले से ही टूट गया था।

जावदोक से (जोर मेरा):

वस्तु का एक स्ट्रिंग प्रतिनिधित्व रिटर्न करता है। सामान्य तौर पर, toString विधि एक स्ट्रिंग लौटाती है जो इस ऑब्जेक्ट को "पाठात्मक रूप से दर्शाती है" । परिणाम एक संक्षिप्त लेकिन जानकारीपूर्ण प्रतिनिधित्व होना चाहिए जो किसी व्यक्ति के लिए पढ़ना आसान है । यह अनुशंसा की जाती है कि सभी उपवर्ग इस विधि को ओवरराइड करें।


23

name()एक "बिल्ट-इन" विधि है enum। यह अंतिम है और आप इसका कार्यान्वयन नहीं बदल सकते। यह एनम निरंतर का नाम देता है जैसा कि लिखा गया है, उदाहरण के लिए ऊपरी मामले में, रिक्त स्थान के बिना आदि।

तुलना MOBILE_PHONE_NUMBERऔर Mobile phone number। कौन सा संस्करण अधिक पठनीय है? मैं दूसरे को मानता हूं। यह अंतर है: name()हमेशा रिटर्न MOBILE_PHONE_NUMBER, toString()वापसी के लिए अतिरंजित हो सकता है Mobile phone number


16
यह सही नहीं है!! Mobile phone numberयदि आप इस तरह के मूल्य को वापस करने के लिए इसे ओवरराइड करते हैं तो ही रिटर्न () रिटर्न अन्यथा यह वापस आ जाएगाMOBILE_PHONE_NUMBER
Spauny

2
@spayny, यह स्पष्ट है कि आपको ओवरराइड करना होगा toString()। पकड़ यह है कि name()अंतिम होने के बाद इसे ओवरराइड नहीं किया जा सकता है।
एलेक्स

13
जवाब में अपने ऊपर टिप्पणी यह 100% सही बनाने के लिए @AlexR आप को शामिल करने की आवश्यकता हो सकती है
artfullyContrived

5
जब तक मैं आपकी टिप्पणियाँ नहीं पढ़ता, मैं @artfullyContrived से सहमत हूँ क्योंकि यह मेरे लिए स्पष्ट नहीं था।
मार्टिनेट

13

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

इसके अतिरिक्त, कोई भी डेटाबेस से डी-सीरियलाइज कर सकता है, उदाहरण के लिए, यह हमेशा जावा में काम करना चाहिए:

MyEnum taco = MyEnum.valueOf(MyEnum.TACO.name());

जबकि इसकी गारंटी नहीं है:

MyEnum taco = MyEnum.valueOf(MyEnum.TACO.toString());

वैसे, मुझे स्पष्ट रूप से "अधिकांश प्रोग्रामर चाहिए" कहने के लिए जावदोक के लिए यह बहुत अजीब लगता है। मैं एक एनम के तारे में बहुत कम उपयोग-मामला पाता हूं, अगर लोग "दोस्ताना नाम" के लिए उपयोग कर रहे हैं जो स्पष्ट रूप से एक खराब उपयोग-मामला है क्योंकि उन्हें i18n के साथ कुछ अधिक संगत उपयोग करना चाहिए, जो कि ज्यादातर मामलों में होगा; नाम () विधि का उपयोग करें।


2
जवाब के लिए धन्यवाद। यह प्रश्न पूछे जाने के लगभग 5 साल हो चुके हैं और मुझे अभी तक एक एनम के लिए स्ट्रैसिंग () विधि का उपयोग करना बाकी है! 99% बार मैं आपके द्वारा बताए गए शब्दों का उपयोग करता हूं: डेटाबेस से / से / के लिए सीरमाइज़िंग और डेसिरिसेलिंग एनम नाम।
स्पायुनि

5

एक व्यावहारिक उदाहरण जब नाम () और toString () का अर्थ अलग-अलग होना एक ऐसा पैटर्न है जहां एकल-मूल्यवान एनम का उपयोग एक सिंगलटन को परिभाषित करने के लिए किया जाता है। यह पहली बार में आश्चर्यजनक लग रहा है लेकिन बहुत मायने रखता है:

enum SingletonComponent {
    INSTANCE(/*..configuration...*/);

    /* ...behavior... */

    @Override
    String toString() {
      return "SingletonComponent"; // better than default "INSTANCE"
    }
}

ऐसे मामले में:

SingletonComponent myComponent = SingletonComponent.INSTANCE;
assertThat(myComponent.name()).isEqualTo("INSTANCE"); // blah
assertThat(myComponent.toString()).isEqualTo("SingletonComponent"); // better

हाँ, आप सही कह रहे हैं ... एक अच्छा उदाहरण है अमरुद की
दुश्मनी

4

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


-1

आप नीचे दिए गए कोड की तरह भी कुछ का उपयोग कर सकते हैं। मैंने गेटर्स और कंस्ट्रक्टर के लिए कुछ बॉयलरप्लेट कोड लिखने से बचने के लिए लोबोक का उपयोग किया।

@AllArgsConstructor
@Getter
public enum RetroDeviceStatus {
    DELIVERED(0,"Delivered"),
    ACCEPTED(1, "Accepted"),
    REJECTED(2, "Rejected"),
    REPAIRED(3, "Repaired");

    private final Integer value;
    private final String stringValue;

    @Override
    public String toString() {
        return this.stringValue;
    }
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.