Enum 값을 문자열 리터럴로 사용


389

Enum에 저장된 값을 문자열 리터럴로 사용하는 가장 좋은 방법은 무엇입니까? 예를 들면 다음과 같습니다.

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

그런 다음 나중에 Mode.mode1문자열 표현을로 반환 하는 데 사용할 수 있습니다 mode1. 계속 전화하지 않아도됩니다 Mode.mode1.toString().

답변:


646

당신은 할 수 없습니다. 네 가지 옵션이 여기 있다고 생각합니다. 네 가지 모두 솔루션을 제공하지만 약간 다른 접근 방식을 제공합니다 ...

옵션 1 : 내장형 name()열거 형을 사용하십시오. 특별한 명명 형식이 필요하지 않은 경우에는 완벽하게 사용할 수 있습니다.

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

옵션 2 : 더 많은 제어를 원하면 열거 속성에 재정의 속성 추가

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;
    }
}

옵션 3 : 열거 형 대신 정적 결승을 사용하십시오.

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() { }
}

옵션 4 : 인터페이스에는 모든 필드가 공개, 정적 및 최종적으로 있습니다.

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
Alex

3
@ kato2가 올바르지 않습니다. .name () 메소드는 컴파일러에 의해 자동으로 생성됩니다
Sean Patrick Floyd

10
JavaDoc : String java.lang.Enum.name () 열거 선언에서 선언 된 그대로,이 열거 정수의 이름을 돌려 줍니다. toString 메소드는보다 사용자에게 친숙한 이름을 리턴 할 수 있으므로 대부분의 프로그래머는이 메소드에 우선하여 toString 메소드를 사용해야합니다. 이 방법은 주로 정확한 이름을 얻는 데 정확성이 결정되는 특수한 상황에서 사용하도록 설계되었으며, 릴리스마다 다릅니다. 이 열거 형 상수의 이름
SuperRetro

@Ryan Stewart의 대변인은 적은 코드와 적은 코드를 필요로합니다. == 버그 가능성이 적습니다
Eric

4
상수를 유지하기 위해 인터페이스를 사용하지 마십시오. 효과적인 Java (제 3 판)는 "유형을 정의하기 위해 인터페이스 만 사용"(항목 22)을 권장합니다.
Olivier Grégoire

481

모든 열거 형에는 name () 및 valueOf (String) 메서드가 모두 있습니다. 전자는 열거 형의 문자열 이름을 반환하고 후자는 이름이 문자열 인 열거 형 값을 제공합니다. 찾고있는 것과 같은가요?

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

Enum 자체에는 정적 valueOf (Class, String)가 있으므로 사용할 수도 있습니다.

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

50
이것은 답변이어야합니다! A ( "A")와 같은 것을 사용하면 오류의 원인이 될 수 있으며 추가 작업이 필요 없습니다!
Firzen

12
@Firzen은 문자열 값에 공백이나 하이픈을 포함 할 수없는 경우에는 허용되지 않습니다 some-really-long-string.

@ceving 공백과 하이픈에 대한 질문은 잘 표현되지 않았습니다. 질문에는 하이픈이있는 예가 표시되지만 하이픈이있는 값을 사용하여 Enum을 만드는 방법은 묻지 않습니다. 대신 질문은 하이픈으로 연결된 값을 지정하지 않고 toString을 호출하지 않고 String 값을 얻는 방법을 요구합니다. 즉, Enum 값이 여전히 Java 명명 규칙을 따라야하며 그러한 문자가 필요한 경우 허용 된 답변에 언급 된 것을 사용해야한다고 언급하면 ​​이것이 더 나은 대답이라고 생각합니다.
Hazok

문자열 변환을 보장하기 위해 메소드를 함께 사용하는 mkyong 에 대한 링크를 추가하고 싶었습니다 . valueOf(String)toUpperCase(Locale)
Unknown Id

2
많은 사람들이 Enum.name ()보다 속성 접근 방식을 선호하는 이유는 Enum.name ()을 기반으로하는 논리가 영원히 가치 이름의 자비에 있기 때문입니다. 미래에 코드가 모두 변경되면 이전의 모든 논리가 Enum 값 세트의 변경 사항을 위반하므로 문제가되지 않는 사소한 문제가 될 수 있습니다. toString () 접근 방식을 재정의하고 사용하면 개발자는 복제, 유효하지 않은 변수 이름 문자 등 사용중인 값을 더 잘 제어 할 수 있습니다. valueOf ()를 재정의하는 것을 잊지 마십시오.
불가분 한

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
추악하고 재사용 할 수 없습니다. Country의 생성자로 문자열 값을 제공 한 다음 열거 형의 toString () 메서드를 재정의하는 것이 훨씬 좋습니다.
greg7gkb

4
이것은 열거가 많고 한두 명의 멤버에 대해 인쇄되는 내용 만 재정의하려는 경우에 유용한 기술입니다.
Donal Fellows

3
이것은 전혀 확장되지 않습니다. 이러지 마
sebnukem

1
이것은 나에게 의미가있다
hanzolo

35

Benny Neugebauer가 언급했듯이 toString ()을 덮어 쓸 수 있습니다. 그러나 대신 각 열거 형 필드의 toString을 덮어 쓰면 다음과 같습니다.

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();
    }
}

정적 필드를 추가하여 모든 필드를 검색하고 모두 인쇄하는 등의 작업도 수행 할 수 있습니다. getValue를 호출하여 각 Enum 항목과 관련된 문자열을 가져 오기만하면됩니다.



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
+ 연산자는 name ()이 아니라 열거 형에서 toString ()을 호출한다는 점에 주목할 가치가 있습니다. 이름이 아닌 다른 것을 반환하기 위해 toString ()을 재정의 할 수도 있습니다. (바람직하지 않더라도)
JB Nizet

1
모두 name()toString()오버라이드 (override) 할 수 있지만, 희망이는 대한 코드를 읽는 분명있을 것입니다 enum이런 일이됩니다.
Peter Lawrey

9
아니요. name ()은 최종적이며 항상 열거 형 선언에 선언 된대로 열거 형의 이름을 반환합니다.
JB 니 제트

1
@JB Nizet, 당신 말이 맞아요. name()입니다 final. 수정 해 주셔서 감사합니다. :)
Peter Lawrey

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.
Larry

아 맞다. getName () 메소드가 필요합니다.이 메소드는 목적을 무효화하므로 불가능합니다.
Jake Roussel

"이름"은 잘못된 필드 이름이며 열거 형의 표준 필드입니다.
Wooff

6

내 열거 형의 경우 각각 1 문자열로 할당되는 것을 생각하지 않습니다. 이것이 열거 형에 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
도달 할 수없는 코드이기 때문에 null을 반환하는 대신 런타임 예외를 던지는 것이 더 낫습니까?
임대

return모든 열거 형으로 열거에 스위치가 종료되기 때문에, 중복입니다.
Danon

5

간단하게 사용할 수 있습니다 :

""+ Modes.mode1

나는 이것을 100 % 확신하지 못하지만 내 지식이가는 한이 캐스트는 필요하지 않습니다. 빈 문자열을 다른 변수와 연결하면 자동으로 변환이 필요합니까, 아니면이 규칙에 예외가 있습니까?
알 수없는 Id

1
맞습니다 "" + Modes.mode1. 올바른 버전은입니다 . 나는 정답을 고쳤다
Buddy

EB의 답변은 또한 파이썬 관용구를 연상케함으로써 이익을 얻습니다 ''.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!");

    }
}

OP의 문제가 4 년 전에 해결 된 것 같지만 StackOverflow에 오신 것을 환영합니다 :)
TDG

1
나처럼 도움이 사람 덕분에, :) 오래된 문제에 대한보다 객관적인 답을 찾고
르낭 Galdino 다 실바

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
어떻게 문제를 해결할 수 있는지 설명해 주시겠습니까?
Phani

이 줄을 사용하여 어디서나이 열거 형을 호출 할 수 있습니다 : int id = 1; 문자열 dayName = Days.getDay (id); 여기 id를 전달하십시오. 해당 아이디에 대한 설명을 "화요일"로 반환합니다.

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;
    }

그러나-이것은 log / println에서 String을 사용해야하거나 java가 toString () 메소드를 자동으로 컴파일 할 때마다 다음과 같은 코드 행에서 작동 할 수 있습니다->

// 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()); 
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.