स्ट्रिंग मानों के रूप में Enum मान का उपयोग करना


389

स्ट्रिंग में शाब्दिक के रूप में Enum में संग्रहीत मानों का उपयोग करने का सबसे अच्छा तरीका क्या है? उदाहरण के लिए:

public enum Modes {
    some-really-long-string,
    mode1,
    mode2,
    mode3
}

फिर बाद में मैं Mode.mode1इसके स्ट्रिंग प्रतिनिधित्व को वापस करने के लिए उपयोग कर सकता था mode1। बिना बुलाए रखने के लिए Mode.mode1.toString()

जवाबों:


646

आप नहीं कर सकते। मुझे लगता है कि आपके पास यहां चार विकल्प हैं। सभी चार एक समाधान प्रदान करते हैं लेकिन थोड़ा अलग दृष्टिकोण के साथ ...

विकल्प एक: एक एनम पर अंतर्निहित का उपयोग करें name()। यह पूरी तरह से ठीक है अगर आपको किसी विशेष नामकरण प्रारूप की आवश्यकता नहीं है।

    String name = Modes.mode1.name(); // Returns the name of this enum constant, exactly as declared in its enum declaration.

विकल्प दो: यदि आप अधिक नियंत्रण चाहते हैं, तो अपने एनम में ओवरराइडिंग गुण जोड़ें

public enum Modes {
    mode1 ("Fancy Mode 1"),
    mode2 ("Fancy Mode 2"),
    mode3 ("Fancy Mode 3");

    private final String name;       

    private Modes(String s) {
        name = s;
    }

    public boolean equalsName(String otherName) {
        // (otherName == null) check is not needed because name.equals(null) returns false 
        return name.equals(otherName);
    }

    public String toString() {
       return this.name;
    }
}

विकल्प तीन: enums के बजाय स्थैतिक फाइनल का उपयोग करें:

public final class Modes {

    public static final String MODE_1 = "Fancy Mode 1";
    public static final String MODE_2 = "Fancy Mode 2";
    public static final String MODE_3 = "Fancy Mode 3";

    private Modes() { }
}

विकल्प चार: इंटरफेस में हर क्षेत्र सार्वजनिक, स्थिर और अंतिम है:

public interface Modes {

    String MODE_1 = "Fancy Mode 1";
    String MODE_2 = "Fancy Mode 2";
    String MODE_3 = "Fancy Mode 3";  
}

46
यह उत्तर वास्तव में गलत है: जैसा कि आप कॉल कर सकते हैं .name()देखें: stackoverflow.com/a/6667365/887836
एलेक्स

3
@ kato2 सही नहीं है। .Name () विधि संकलक द्वारा स्वचालित रूप से बनाई गई है
सीन पैट्रिक फ्लोयड

10
JavaDoc: स्ट्रिंग java.lang.Enum.name () इस एनम स्थिरांक का नाम लौटाता है, जैसा कि इसके एनम घोषणा में घोषित किया गया है। अधिकांश प्रोग्रामर को पहले की तुलना में इस .String पद्धति का उपयोग करना चाहिए, क्योंकि String पद्धति अधिक उपयोगकर्ता-अनुकूल नाम वापस कर सकती है। यह विधि मुख्य रूप से विशेष परिस्थितियों में उपयोग के लिए डिज़ाइन की गई है जहाँ शुद्धता सटीक नाम प्राप्त करने पर निर्भर करती है, जो रिलीज़ से रिलीज़ होने तक भिन्न नहीं होगी। रिटर्न: इस एनम स्थिरांक का नाम
SuperRetro

@ रेयान स्टीवर्ट के awser को कम कोड और कम कोड की आवश्यकता होती है == बग की कम संभावना
Eric

4
स्थिरांक रखने के लिए इंटरफेस का उपयोग न करें: प्रभावी जावा (तीसरा संस्करण) "केवल परिभाषित प्रकारों के लिए इंटरफेस का उपयोग करने" (आइटम 22) की सिफारिश करता है।
ओलिवियर ग्रेजायर

481

हर एनम में एक नाम () और एक वैल्यू (स्ट्रिंग) विधि होती है। पूर्व एनम का स्ट्रिंग नाम देता है, और बाद वाला एनम मान देता है जिसका नाम स्ट्रिंग है। क्या यह वैसा है जैसा आप खोज रहे हैं?

String name = Modes.mode1.name();
Modes mode = Modes.valueOf(name);

Enum पर ही एक स्थिर valueOf (क्लास, स्ट्रिंग) भी है, इसलिए आप भी उपयोग कर सकते हैं

Modes mode = Enum.valueOf(Modes.class, name);

50
यह एक उत्तर होना चाहिए! A ("A") जैसी किसी चीज़ का उपयोग करना त्रुटियों का स्रोत हो सकता है और यह संवेदनहीन अतिरिक्त काम है!
फिरोजेन

12
@Firzen नहीं अगर स्ट्रिंग मान में रिक्त स्थान या हाइफ़न शामिल करने की अनुमति है, जो कि मामला है some-really-long-string
छत

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

मैं mkyong के लिए एक लिंक जोड़ना चाहता था जो स्ट्रिंग रूपांतरण को सुनिश्चित करने के लिए valueOf(String)संयोजन में विधि का उपयोग करता है toUpperCase(Locale)
अज्ञात आईडी

2
बहुत से लोग Enum.name () पर संपत्ति के दृष्टिकोण को पसंद करते हैं, यही कारण है कि Enum.name () के आसपास स्थित तर्क तब मूल्य नामों की दया पर हमेशा के लिए होता है। यदि कोड भविष्य में हर परिवर्तन करता है तो यह एक गैर तुच्छ मुद्दे में बदल सकता है क्योंकि पिछले सभी तर्क Enum मान सेट में परिवर्तन पर टूट जाएंगे। ओवरराइड करने और उपयोग करने से (toString) दृष्टिकोण डुप्लिकेट, गैर मान्य वैरिएबल नाम अक्षर आदि सहित उपयोग में मूल्यों पर अधिक नियंत्रण रखने की अनुमति देता है। बस वैल्यूऑफ को ओवरराइड करना भी मत भूलना ()।
अविभाज्य

79

आप toString()प्रत्येक एनम मान के लिए विधि को ओवरराइड कर सकते हैं ।

उदाहरण:

public enum Country {

  DE {
    @Override
    public String toString() {
      return "Germany";
    }
  },
  IT {
    @Override
    public String toString() {
      return "Italy";
    }
  },
  US {
    @Override
    public String toString() {
      return "United States";
    }
  }

}

उपयोग:

public static void main(String[] args) {
  System.out.println(Country.DE); // Germany
  System.out.println(Country.IT); // Italy
  System.out.println(Country.US); // United States
}

2
यह मुझे पंसद है। कोई कारण नहीं है कि आगे की कार्यक्षमता के साथ एक वर्ग के रूप में एक एनम का उपयोग करें जैसे कि सभी मूल्यों की एक सूची प्राप्त करें, प्रत्येक प्रकार की एक स्ट्रिंग प्राप्त करें, आदि
diegosasw

8
बदसूरत और पुन: प्रयोज्य नहीं। देश के लिए कंस्ट्रक्टर के रूप में एक स्ट्रिंग मूल्य प्रदान करने के लिए बेहतर है और फिर एनम के लिए स्ट्रींग () विधि को ओवरराइड करें।
greg7gkb

4
यह एक अच्छी तकनीक है, जब आपके पास काफी बड़ी गणना है और केवल एक या दो सदस्यों के लिए क्या चीजें प्रिंट करना चाहते हैं।
डोना फेलो

3
यह बिल्कुल भी पैमाना नहीं है। यह मत करो।
sebnukem

1
इससे मुझे समझ में आता है
हनज़ोलो

35

जैसा कि बेनी न्युगबॉएर उल्लेख करते हैं, आप स्ट्रीटिंग () को अधिलेखित कर सकते हैं। हालाँकि, प्रत्येक एनुम क्षेत्र के लिए स्ट्रीटिंग को ओवरराइट करने के बजाय मुझे ऐसा कुछ अधिक पसंद है:

public enum Country{
    SPAIN("España"),
    ITALY("Italia"),
    PORTUGAL("Portugal");


    private String value;

    Country(final String value) {
        this.value = value;
    }

    public String getValue() {
        return value;
    }

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

आप सभी क्षेत्रों को पुनः प्राप्त करने के लिए, उन सभी को प्रिंट करने के लिए एक स्थैतिक विधि भी जोड़ सकते हैं, आदि बस कॉल करें। प्रत्येक Enum आइटम से संबंधित स्ट्रिंग प्राप्त करने के लिए getValue



21
public enum Modes {
  MODE1("Mode1"),
  MODE2("Mode2"),
  MODE3("Mode3");

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

आप जहां चाहें एनम से एक स्ट्रिंग के रूप में मूल्य प्राप्त करना चाहते हैं नीचे एक कॉल कर सकते हैं।

Modes.MODE1.getvalue();

यह स्ट्रिंग के रूप में "Mode1" लौटाएगा।


6

आप Mode.mode1.name()हालांकि आप अक्सर ऐसा करने की जरूरत नहीं है का उपयोग कर सकते हैं ।

Mode mode =
System.out.println("The mode is "+mode);

6
यह ध्यान देने योग्य है कि + संचालक enum पर toString () को कॉल करेगा, और नाम नहीं ()। और स्ट्रींग () नाम के अलावा कुछ भी वापस करने के लिए ओवरराइड किया जा सकता है (भले ही यह वांछनीय न हो)
जेबी निज़ेट

1
दोनों name()और toString()ओवरराइड किया जा सकता है, लेकिन उम्मीद है कि इस के लिए कोड को पढ़ने से स्पष्ट हो जाएगा enumअगर यह हो रहा है।
पीटर लॉरी जूल

9
नाम () अंतिम है, और हमेशा एनम के नाम को अपनी एनुम घोषणा में घोषित किया गया है।
जेबी निज़ात

1
@ जेबी निज़ात, आप सही कह रहे हैं। name()है final। मुझे सही करने के लिए धन्यवाद। :)
पीटर लॉरी

6

जहां तक ​​मुझे पता है, नाम पाने का एकमात्र तरीका होगा

Mode.mode1.name();

यदि आपको वास्तव में इस तरह की आवश्यकता है, तो आप कर सकते हैं:

public enum Modes {
    mode1 ("Mode1"),
    mode2 ("Mode2"),
    mode3 ("Mode3");

    private String name;       

    private Modes(String s) {
        name = s;
    }
}

1
लेकिन इस मामले में, Mode.mode1अभी भी टाइप नहीं है String
लैरी

अरे हाँ। आपको एक getName () विधि की आवश्यकता होगी, जो उद्देश्य को हरा देती है, इसलिए नहीं, आप ऐसा नहीं कर सकते।
जेक रौसेल

"नाम" खराब क्षेत्र का नाम है, यह ईनम का क्षेत्र है।
वूफ

6

अपनी पहेली के लिए मैं वास्तव में उन्हें 1 स्ट्रिंग के साथ आवंटित होने के बारे में सोचना पसंद नहीं करता। इस तरह से मैं enums पर एक toString () पद्धति को लागू करता हूं।

enum Animal
{
    DOG, CAT, BIRD;
    public String toString(){
        switch (this) {
            case DOG: return "Dog";
            case CAT: return "Cat";
            case BIRD: return "Bird";
        }
        return null;
    }
}

1
एक रनटाइम अपवाद को फेंकना बेहतर होगा क्योंकि यह अनुपयोगी कोड होना चाहिए?
किराए

returnनिरर्थक है क्योंकि सभी enums साथ enums पर स्विच समाप्त जाता है।
डैनॉन

5

आप बस का उपयोग कर सकते हैं:

""+ Modes.mode1

मुझे इस पर 100% यकीन नहीं है लेकिन जहाँ तक मेरी जानकारी है कि यह कास्ट आवश्यक नहीं है, क्या यह है? किसी अन्य चर के साथ एक खाली स्ट्रिंग को समाप्‍त करने के लिए स्वचालित रूप से रूपांतरण के लिए कॉल करना चाहिए, या इस नियम के कोई अपवाद हैं?
अज्ञात आईडी

1
आप सही हैं, सही संस्करण होना चाहिए "" + Modes.mode1। मैंने जवाब तय किया
बडी

ईथ का जवाब भी अजगर के मुहावरे की याद दिलाकर लाभ देता है ''.join()
एन्थ्रोपिक एंड्रॉइड

5

आपकी समस्या के लिए मेरा समाधान!

import java.util.HashMap;
import java.util.Map;

public enum MapEnumSample {
    Mustang("One of the fastest cars in the world!"), 
    Mercedes("One of the most beautiful cars in the world!"), 
    Ferrari("Ferrari or Mercedes, which one is the best?");

    private final String description;
    private static Map<String, String> enumMap;

    private MapEnumSample(String description) {
        this.description = description;
    }

    public String getEnumValue() {
        return description;
    }

    public static String getEnumKey(String name) {
        if (enumMap == null) {
            initializeMap();
        }
        return enumMap.get(name);
    }

    private static Map<String, String> initializeMap() {
        enumMap = new HashMap<String, String>();
        for (MapEnumSample access : MapEnumSample.values()) {
            enumMap.put(access.getEnumValue(), access.toString());
        }
        return enumMap;
    }

    public static void main(String[] args) {

        // getting value from Description
        System.out.println(MapEnumSample.getEnumKey("One of the fastest cars in the world!"));

        // getting value from Constant
        System.out.println(MapEnumSample.Mustang.getEnumValue());

        System.out.println(MapEnumSample.getEnumKey("One of the most beautiful cars in the world!"));
        System.out.println(MapEnumSample.Mercedes.getEnumValue());

        // doesnt exist in Enum
        System.out.println("Mustang or Mercedes, which one is the best?");
        System.out.println(MapEnumSample.getEnumKey("Mustang or Mercedes, which one is the best?") == null ? "I don't know!" : "I believe that "
                + MapEnumSample.getEnumKey("Ferrari or Mustang, which one is the best?") + " is the best!.");

        // exists in Enum
        System.out.println("Ferrari or Mercedes, wich one is the best?");
        System.out.println(MapEnumSample.getEnumKey("Ferrari or Mercedes, which one is the best?") == null ? "I don't know!" : "I believe that "
                + MapEnumSample.getEnumKey("Ferrari or Mercedes, which one is the best?") + " is the best!");

    }
}

ऐसा लगता है कि ओपी की समस्या 4 साल पहले हल हो गई थी, लेकिन स्टैकऑवरफ्लो में आपका स्वागत है :)
TDG

1
धन्यवाद, बस मेरी तरह किसी की मदद करने के लिए, पुरानी समस्याओं के अधिक उद्देश्य के जवाब की तलाश में :)
रेनन गेलदिनो दा सिल्वा

3

Enum सिर्फ एक छोटा सा विशेष वर्ग है। एनम अतिरिक्त क्षेत्रों को स्टोर कर सकते हैं, तरीकों को लागू कर सकते हैं आदि। उदाहरण के लिए

public enum Modes {
    mode1('a'),
    mode2('b'),
    mode3('c'),
    ;
    char c;

    private Modes(char c) {
        this.c = c;
    }
    public char character() {
        return c;
    }
}

अब आप कह सकते हैं:

System.out.println(Modes.mode1.character())

और आउटपुट देखें: a


3
package com.common.test;

public  enum Days {


    monday(1,"Monday"),tuesday(2,"Tuesday"),wednesday(3,"Wednesday"),
    thrusday(4,"Thrusday"),friday(5,"Friday"),saturday(6,"Saturday"),sunday(7,"Sunday");

    private int id;
    private String desc;


    Days(int id,String desc){
        this.id=id;
        this.desc=desc;
    }

    public static String getDay(int id){

        for (Days day : Days.values()) {
            if (day.getId() == id) {
                return day.getDesc();
            }
        }
        return null;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getDesc() {
        return desc;
    }

    public void setDesc(String desc) {
        this.desc = desc;
    }



};

1
क्या आप pls बता सकते हैं कि यह समस्या का समाधान कैसे होगा?
फणी

आप इस लाइन का उपयोग करके कहीं भी इस एनम को कॉल कर सकते हैं: int id = 1; स्ट्रिंग डे नाम = Days.getDay (आईडी); , यहाँ आईडी पास करें। यह उस आईडी के लिए विवरण लौटाएगा जो "मंगलवार" है

2

इस विधि को किसी भी काम करना चाहिए enum:

public enum MyEnum {
    VALUE1,
    VALUE2,
    VALUE3;

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

    public static DataType forValue(int value) {
        return values()[value];
    }

    public String toString() {
        return forValue(getValue()).name();
    }
}

2
public enum Environment
{
    PROD("https://prod.domain.com:1088/"),
    SIT("https://sit.domain.com:2019/"),
    CIT("https://cit.domain.com:8080/"),
    DEV("https://dev.domain.com:21323/");

    private String url;

    Environment(String envUrl) {
        this.url = envUrl;
    }

    public String getUrl() {
        return url;
    }
}

String prodUrl = Environment.PROD.getUrl();

यह प्रिंट होगा:

https://prod.domain.com:1088/

एनम स्ट्रिंग स्थिरांक के लिए यह डिजाइन ज्यादातर मामलों में काम करता है।


0

कई कोशिशों के बाद मैं इस समाधान के साथ आया हूं

public static enum Operation {

    Addition, Subtraction, Multiplication, Division,;

    public String getUserFriendlyString() {
        if (this==Addition) {
            return " + ";
        } else if (this==Subtraction) {
            return " - ";
        } else if (this==Multiplication) {
            return " * ";
        } else if (this==Division) {
            return " / ";
        }
        return "undefined";
       }
}

0

आप यह कोशिश कर सकते हैं:

public enum Modes {
    some-really-long-string,
    mode1,
    mode2,
    mode3;

    public String toString(){
        switch(this) {
            case some-really-long-string:
                return "some-really-long-string";
            case mode2:
                return "mode2";
            default: return "undefined";
        }
    }

}


0

मैंने पाया कि यह एक प्रकार की त्रुटि को रोकने के लिए अधिक आसान है:

public enum Modes {
    some-really-long-string,
    mode1,
    mode2,
    mode3;

    String str;

    Modes(){
        this.str = super.name();
    }

    @Override
    @NonNull
    public String toString() {
        return str;
    }

हालाँकि - यह तब काम कर सकता है जब आपको लॉग / प्रिटंल पर स्ट्रिंग का उपयोग करने की आवश्यकता होती है या जब भी जावा स्वचालित रूप से () विधि से संकलित करता है, लेकिन इस तरह कोड लाइन पर ->

// sample method that require (string,value)
intent.putExtra(Modes.mode1 ,shareElement.getMode()); // java error
// first argument enum does not return value

उपर्युक्त के बजाय आपको अभी भी .name() इस तरह के मामलों में एनम का विस्तार करना होगा और उपयोग करना होगा:

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