2009-07-03 7 views
113

मैं अपने स्ट्रिंग मान (या संभवतः किसी अन्य मूल्य) से एक enum देखना चाहता हूं। मैंने निम्नलिखित कोड का प्रयास किया है लेकिन यह प्रारंभिक में स्थिर की अनुमति नहीं देता है। क्या कोई आसान तरीका है?मैं अपने स्ट्रिंग मान से जावा एनम कैसे देख सकता हूं?

public enum Verbosity { 

    BRIEF, NORMAL, FULL; 

    private static Map<String, Verbosity> stringMap = new HashMap<String, Verbosity>(); 

    private Verbosity() { 
     stringMap.put(this.toString(), this); 
    } 

    public static Verbosity getVerbosity(String key) { 
     return stringMap.get(key); 
    } 
}; 
+0

आईआईआरसी, जो एक एनपीई देता है क्योंकि स्थैतिक प्रारंभिकता नीचे की जाती है (यानी शीर्ष पर एनम स्थिरांक 'स्ट्रिंग मैप प्रारंभिकरण' तक पहुंचने से पहले बनाए जाते हैं)। सामान्य समाधान एक घोंसला वर्ग का उपयोग करना है। –

+0

इस तरह की तीव्र प्रतिक्रिया के लिए सभी को धन्यवाद। (एफडब्ल्यूआईडब्ल्यू मुझे इस समस्या के लिए सूर्य जावाडॉक्स बहुत उपयोगी नहीं मिला)। –

+0

लाइब्रेरी समस्या से यह वास्तव में एक भाषा मुद्दा है। हालांकि, मुझे लगता है कि एपीआई दस्तावेज़ जेएलएस (हालांकि शायद भाषा डिजाइनरों द्वारा नहीं) से अधिक पढ़े जाते हैं, इसलिए इस तरह की चीजें java.lang दस्तावेज़ों में अधिक महत्व रखनी चाहिए। –

उत्तर

171

valueOf विधि है जो स्वचालित रूप से प्रत्येक Enum लिए बनाया जाता है का उपयोग करें।

Verbosity.valueOf("BRIEF") == Verbosity.BRIEF 

मनमाने ढंग से मूल्यों के लिए शुरू के साथ:

public static Verbosity findByAbbr(String abbr){ 
    for(Verbosity v : values()){ 
     if(v.abbr().equals(abbr)){ 
      return v; 
     } 
    } 
    return null; 
} 

केवल कार्यान्वयन मानचित्र अगर आपके प्रोफाइलर आप के लिए कहता है पर ले जाने के बाद में।

मुझे पता है कि यह सभी मूल्यों पर पुनरावृत्ति कर रहा है, लेकिन केवल 3 enum मानों के साथ यह किसी भी अन्य प्रयास के लायक नहीं है, वास्तव में जब तक आपके पास बहुत सारे मूल्य नहीं हैं, तो मैं एक मानचित्र से परेशान नहीं होगा, यह पर्याप्त तेज़ होगा।

+0

धन्यवाद - और यदि मैं जानता हूं कि मान अभी भी अलग हैं –

+0

यदि आप "v.abbr()" के बजाय "v.abbr.equals" का उपयोग कर सकते हैं तो आप वर्ग सदस्य 'abbr' तक पहुंच सकते हैं। "। – zatziky

+3

इसके अलावा, मनमाने ढंग से मूल्यों के लिए (दूसरा मामला) शून्य (* यानी) लौटने की बजाए 'अवैध आर्ग्यूमेंट अपवाद' फेंकने पर विचार करें।* जब कोई मिलान नहीं मिलता है) - इस प्रकार जेडीके 'Enum.valueOf (..)' वैसे भी करता है। –

6

और आप valueOf() का उपयोग नहीं कर सकते हैं?

संपादित करें: बीटीडब्ल्यू, एक enum में स्थिर {} का उपयोग करने से आपको रोक नहीं रहा है।

+0

या enum वर्ग पर कृत्रिम 'valueOf', तो आपको enum class' class' निर्दिष्ट करने की आवश्यकता नहीं है। –

+0

बेशक, इसमें सिर्फ एक जावाडोक प्रविष्टि नहीं थी इसलिए इसे लिंक करना मुश्किल था। – Fredrik

+1

आप जेएलएस से लिंक कर सकते हैं: http://java.sun.com/docs/books/jls/third_edition/html/classes.html#302265 – newacct

103

आप करीब हैं। मनमाने ढंग से मूल्यों के लिए, निम्न की तरह कुछ प्रयास करें:

public enum Day { 

    MONDAY("M"), TUESDAY("T"), WEDNESDAY("W"), 
    THURSDAY("R"), FRIDAY("F"), SATURDAY("Sa"), SUNDAY("Su"), ; 

    private final String abbreviation; 

    // Reverse-lookup map for getting a day from an abbreviation 
    private static final Map<String, Day> lookup = new HashMap<String, Day>(); 

    static { 
     for (Day d : Day.values()) { 
      lookup.put(d.getAbbreviation(), d); 
     } 
    } 

    private Day(String abbreviation) { 
     this.abbreviation = abbreviation; 
    } 

    public String getAbbreviation() { 
     return abbreviation; 
    } 

    public static Day get(String abbreviation) { 
     return lookup.get(abbreviation); 
    } 
} 
+2

"आप" Day.values ​​() "का उपयोग कर सकते हैं ... –

+0

आह, तो मैं कर सकता हूं। धन्यवाद। – Lyle

+2

क्लासलोडर समस्याओं के कारण यह विधि विश्वसनीय काम नहीं करेगी। मैं इसकी अनुशंसा नहीं करता हूं और मैंने देखा है कि यह नियमित रूप से विफल रहता है क्योंकि लुकअप मानचित्र एक्सेस होने से पहले तैयार नहीं है। आपको enum के बाहर या किसी अन्य वर्ग में "लुकअप" डालना होगा ताकि वह पहले लोड हो सके। –

12

@ लेल का जवाब खतरनाक है और मैंने देखा है कि यह विशेष रूप से काम नहीं करता है यदि आप enum को एक स्थिर आंतरिक कक्षा बनाते हैं। इसके बजाय मैंने इस तरह कुछ उपयोग किया है जो enums से पहले बूटस्ट्रैपसिंगटन मानचित्र लोड करेगा।

संपादितइस आधुनिक JVMs के साथ किसी भी अधिक एक समस्या (JVM 1.6 या अधिक) नहीं होना चाहिए, लेकिन मैं अभी भी JRebel में समस्याएं हैं लेकिन मैं इसे जांचना करने का मौका नहीं पड़ा है लगता है।

मुझे पहले लोड:

public final class BootstrapSingleton { 

     // Reverse-lookup map for getting a day from an abbreviation 
     public static final Map<String, Day> lookup = new HashMap<String, Day>(); 
    } 

अब enum निर्माता में लोड: (

public enum Day { 
     MONDAY("M"), TUESDAY("T"), WEDNESDAY("W"), 
     THURSDAY("R"), FRIDAY("F"), SATURDAY("Sa"), SUNDAY("Su"), ; 

     private final String abbreviation; 

     private Day(String abbreviation) { 
      this.abbreviation = abbreviation; 
      BootstrapSingleton.lookup.put(abbreviation, this); 
     } 

     public String getAbbreviation() { 
      return abbreviation; 
     } 

     public static Day get(String abbreviation) { 
      return lookup.get(abbreviation); 
     } 
    } 

आप एक आंतरिक enum है, तो आप सिर्फ enum परिभाषा ऊपर मानचित्र को परिभाषित करने और है कि कर सकते हैं में सिद्धांत) पहले लोड होना चाहिए।

+2

"खतरनाक" को परिभाषित करने की आवश्यकता है और क्यों एक आंतरिक वर्ग कार्यान्वयन महत्वपूर्ण है। यह एक शीर्ष से नीचे स्थिर परिभाषा मुद्दा है, लेकिन इस प्रश्न के लिंक के साथ किसी अन्य संबंधित उत्तर में कामकाजी कोड है जो एनम उदाहरण पर एक स्थिर मानचित्र का उपयोग करता है, जिसे उपयोगकर्ता द्वारा परिभाषित मूल्य से "प्राप्त" विधि के साथ किया जाता है एनम प्रकार http://stackoverflow.com/questions/604424/lookup-enum-by-string-value –

+1

@ मूल समस्या मूल समस्या JVMs (पूर्व 1.6) या अन्य JVMs (आईबीएम) या हॉटकोड swappers (जेआरबेल) के कारण थी। यह मुद्दा आधुनिक जेवीएम में नहीं होना चाहिए, इसलिए मैं अपना जवाब हटा सकता हूं। –

+0

ध्यान दें कि वास्तव में कस्टम कंपाइलर कार्यान्वयन और रनटाइम अनुकूलन के कारण यह संभव है ... आदेश को संशोधित किया जा सकता है, जिसके परिणामस्वरूप त्रुटि हो सकती है। हालांकि, यह spec का उल्लंघन करने के लिए प्रतीत होता है। –

1

शायद, इसे देखें। यह मेरे लिए काम कर रहा है। इसका उद्देश्य 'लाल' को '/ red_color' के साथ देखना है। static map घोषित करना और इसमें enum एस लोड करना केवल एक बार कुछ प्रदर्शन लाभ लाएगा यदि enum एस कई हैं।

public class Mapper { 

public enum Maps { 

    COLOR_RED("/red_color", "RED"); 

    private final String code; 
    private final String description; 
    private static Map<String, String> mMap; 

    private Maps(String code, String description) { 
     this.code = code; 
     this.description = description; 
    } 

    public String getCode() { 
     return name(); 
    } 

    public String getDescription() { 
     return description; 
    } 

    public String getName() { 
     return name(); 
    } 

    public static String getColorName(String uri) { 
     if (mMap == null) { 
      initializeMapping(); 
     } 
     if (mMap.containsKey(uri)) { 
      return mMap.get(uri); 
     } 
     return null; 
    } 

    private static void initializeMapping() { 
     mMap = new HashMap<String, String>(); 
     for (Maps s : Maps.values()) { 
      mMap.put(s.code, s.description); 
     } 
    } 
} 
} 

कृपया अपने विचारों को प्रस्तुत करें।

-2

आप के रूप में ऊपर गैरेथ डेविस & ब्रैड गदा ने सुझाव दिया Enum::valueOf() फ़ंक्शन का उपयोग करें, लेकिन आप IllegalArgumentException अगर इस्तेमाल किया स्ट्रिंग enum में मौजूद नहीं है कि फेंक दिया होगा संभाल सुनिश्चित करें।

4

जावा भाषा विशिष्टता 7 में a example है!जो स्वयं के संदर्भ के साथ मानचित्र के आरंभ पर आपके प्रश्न को दर्शाता है।

+1

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

0

आप नीचे दिए गए कोड के रूप में अपने Enum परिभाषित कर सकते हैं:

public enum Verbosity 
{ 
    BRIEF, NORMAL, FULL, ACTION_NOT_VALID; 
    private int value; 

    public int getValue() 
    { 
    return this.value; 
    } 

    public static final Verbosity getVerbosityByValue(int value) 
    { 
    for(Verbosity verbosity : Verbosity.values()) 
    { 
     if(verbosity.getValue() == value) 
      return verbosity ; 
    } 

    return ACTION_NOT_VALID; 
    } 

    @Override 
    public String toString() 
    { 
     return ((Integer)this.getValue()).toString(); 
    } 
}; 

See following link for more clarification

5

जावा 8 के साथ आप इस तरह से प्राप्त कर सकते:

public static Verbosity findByAbbr(final String abbr){ 
    return Arrays.stream(values()).filter(value -> value.abbr().equals(abbr)).findFirst().orElse(null); 
} 
1

मामले में यह मदद करता है अन्य, विकल्प जो मैं पसंद करता हूं, जो यहां सूचीबद्ध नहीं है,का उपयोग करता है 10:

public enum Vebosity { 
    BRIEF("BRIEF"), 
    NORMAL("NORMAL"), 
    FULL("FULL"); 

    private String value; 
    private Verbosity(final String value) { 
     this.value = value; 
    } 

    public String getValue() { 
     return this.value; 
    } 

    private static ImmutableMap<String, Verbosity> reverseLookup = 
      Maps.uniqueIndex(Arrays.asList(Verbosity.values)), Verbosity::getValue); 

    public static Verbosity fromString(final String id) { 
     return reverseLookup.getOrDefault(id, NORMAL); 
    } 
} 
डिफ़ॉल्ट आप null उपयोग कर सकते हैं के साथ

, आप throw IllegalArgumentException या अपने fromString एक Optional लौट सकते हैं कर सकते हैं, जो कुछ भी व्यवहार आप पसंद करते हैं।

संबंधित मुद्दे