enum과 int / String을 편리하게 매핑


108

유한 한 수의 값만 취할 수있는 변수 / 매개 변수로 작업 할 때 다음과 enum같이 항상 Java를 사용하려고합니다 .

public enum BonusType {
  MONTHLY, YEARLY, ONE_OFF
}

내 코드 안에 있으면 잘 작동합니다. 그러나 동일한 목적으로 일반 int(또는 String) 값을 사용하는 다른 코드와 인터페이스해야하는 경우가 많거나 데이터가 숫자 또는 문자열로 저장된 데이터베이스에서 읽거나 써야합니다.

이 경우 두 가지 방법을 모두 변환 할 수 있도록 각 열거 형 값을 정수와 연결하는 편리한 방법을 원합니다 (즉, "가역 열거 형"이 필요합니다).

enum에서 int로 이동하는 것은 쉽습니다.

public enum BonusType {
  public final int id;

  BonusType(int id) {
    this.id = id;
  }
  MONTHLY(1), YEARLY(2), ONE_OFF(3);
}

그런 다음 int 값에 BonusType x = MONTHLY; int id = x.id;.

그러나, 나는 반대로, 즉 int에서 enum으로가는 좋은 방법을 볼 수 없습니다. 이상적으로는

BonusType bt = BonusType.getById(2); 

내가 생각 해낼 수있는 유일한 해결책은 다음과 같습니다.

  • BonusType.values()"int-> enum"맵을 채우는 데 사용하는 조회 메소드를 enum 에 넣은 다음이를 캐시하여 조회에 사용합니다. 작동하지만이 메서드를 사용하는 각 열거 형에 동일하게 복사해야합니다. :-(.
  • 조회 메소드를 정적 유틸리티 클래스에 넣으십시오. 그런 다음 하나의 "조회"메서드 만 필요하지만 임의의 열거 형에 대해 작동하려면 리플렉션을 사용하여 조작해야합니다.

두 가지 방법 모두 이러한 간단한 (?) 문제에 대해 매우 어색해 보입니다.

다른 아이디어 / 통찰이 있습니까?


1
나는 <3 자바 열거 형이지만 정확히 이런 이유로 싫어합니다! 정말 못생긴 결함을 제외하고는 항상 완벽 해 보입니다 ...
Chris Thompson

8
enum-> int의 경우 그냥 사용할 수 있습니다ordinal()
davin

1
당신의 id-value는 당신이 결정할 수 있습니까 (즉, 당신은 사용할 수 없습니다 .ordinal()), 아니면 외부 세력에 의해 결정됩니까?
Paŭlo Ebermann

2
@davin : 예, 누군가 열거 형 선언을 재정렬하거나 중간에있는 값을 삭제하는 순간 코드가 깨지게하십시오. 강력한 솔루션이 아닌 것 같습니다 :-/.
sleske

1
"ordinal ()"을 사용하는 @davin은 가능한 한 피해야합니다. 언어 사양에 있습니다
DPM

답변:


37

http://www.javaspecialists.co.za/archive/Issue113.html

솔루션은 열거 형 정의의 일부로 int 값을 사용하여 사용자와 유사하게 시작됩니다. 그런 다음 계속해서 제네릭 기반 조회 유틸리티를 만듭니다.

public class ReverseEnumMap<V extends Enum<V> & EnumConverter> {
    private Map<Byte, V> map = new HashMap<Byte, V>();
    public ReverseEnumMap(Class<V> valueType) {
        for (V v : valueType.getEnumConstants()) {
            map.put(v.convert(), v);
        }
    }

    public V get(byte num) {
        return map.get(num);
    }
}

이 솔루션은 훌륭하며 모든 열거 형 유형이 암시 적으로 Enum 인터페이스를 상속한다는 사실을 기반으로하기 때문에 '반사 처리'가 필요하지 않습니다.


서수를 사용하지 않습니까? Sleske는 열거 형 값이 다시 정렬 될 때 서 수가 변경되기 때문에 id를 사용합니다.
extraneon

아니요, 서수를 사용하지 않습니다. 명시 적으로 정의 된 int 값에 의존합니다. 해당 int 값은 맵 키로 사용됩니다 (v.convert ()에서 반환 됨).
제프

2
이 솔루션이 정말 마음에 듭니다. 이것이 당신이 얻을 수있는 가장 일반적인 것 같습니다.
sleske

+1. 내 유일한 메모는 내 백업 값이 더 클 수 있기 때문에 Number대신을 사용한다는 것 Byte입니다.
Ivaylo Slavov

3
정말로 그리고 진정으로 질문을 읽으십시오. 자신의 코드를 통해 전파하지 않으려는 정수를 정의한 레거시 데이터베이스 또는 외부 시스템을 처리하는 경우 정확히 이러한 경우 중 하나입니다. 서수는 열거 형의 값을 유지하는 매우 취약한 방법이며 그 이상으로 질문에 언급 된 특정 경우에는 쓸모가 없습니다.
제프

327

열거 형 → 정수

yourEnum.ordinal()

int → 열거 형

EnumType.values()[someInt]

문자열 → 열거 형

EnumType.valueOf(yourString)

열거 형 → 문자열

yourEnum.name()

참고 :
올바르게 지적했듯이 ordinal()버전마다 "불안정"할 수 있습니다. 이것이 내가 항상 데이터베이스에 문자열로 상수를 저장하는 정확한 이유입니다. (실제로 MySql을 사용할 때 MySql 열거 형 으로 저장합니다 !)


2
+1 이것은 분명한 정답입니다. 참고, 당신은 콘크리트 열거 형을 사용하고 같은 단지 문자열을 받아 한 존재 valueOf에 대한 하나의 인자 방법이있다하더라도 (예 BonusType.valueOf("MONTHLY"))
팀 벤더

18
ordinal()열거 형 값 목록이 재정렬되거나 값이 삭제되면 깨지기 때문에 사용하면 문제가있는 해결책으로 떠 오릅니다. 또한 이것은 int 값이 0 ... n 인 경우에만 실용적입니다 (나는 종종 그렇지 않은 것으로 나타났습니다).
sleske

4
@sleske, 상수 삭제를 시작하면 어쨌든 기존 지속 데이터에 문제가 있습니다. (이와 관련하여 내 답변을 업데이트했습니다.)
aioobe

3
values()배열 사용은 모든 값이 ID에 대해 0 인덱싱되고 순서대로 선언 된 경우에만 작동합니다. (나는이 확인 테스트 당신은 선언하는 경우 FOO(0), BAR(2), BAZ(1);values[1] == BARvalues[2] == BAZ전달 된 식별자에도 불구하고.)
corsiKa

2
@glowcoder, 당연히 정수 인수는 단순히 열거 형 개체의 필드입니다. enum 객체와 관련된 서수 상수와는 아무 관련이 없습니다 (일 수도 있음 double).
aioobe

29

나는 이것을 웹에서 발견했고, 구현하기 매우 유용하고 간단했습니다. 이 솔루션은 내가 만든 것이 아닙니다.

http://www.ajaxonomy.com/2007/java/making-the-most-of-java-50-enum-tricks

public enum Status {
 WAITING(0),
 READY(1),
 SKIPPED(-1),
 COMPLETED(5);

 private static final Map<Integer,Status> lookup 
      = new HashMap<Integer,Status>();

 static {
      for(Status s : EnumSet.allOf(Status.class))
           lookup.put(s.getCode(), s);
 }

 private int code;

 private Status(int code) {
      this.code = code;
 }

 public int getCode() { return code; }

 public static Status get(int code) { 
      return lookup.get(code); 
 }

}


S / EnumSet.allOf (Status.class) /Status.values ()
jelinson

8

이 질문에 대한 답변은 Java 8 릴리스와 함께 구식입니다.

  1. 서수는 데이터베이스와 같은 JVM 외부에서 지속되는 경우 불안정하므로 서수를 사용하지 마십시오.
  2. 키 값으로 정적지도를 만드는 것은 비교적 쉽습니다.

public enum AccessLevel {
  PRIVATE("private", 0),
  PUBLIC("public", 1),
  DEFAULT("default", 2);

  AccessLevel(final String name, final int value) {
    this.name = name;
    this.value = value;
  }

  private final String name;
  private final int value;

  public String getName() {
    return name;
  }

  public int getValue() {
    return value;
  }

  static final Map<String, AccessLevel> names = Arrays.stream(AccessLevel.values())
      .collect(Collectors.toMap(AccessLevel::getName, Function.identity()));
  static final Map<Integer, AccessLevel> values = Arrays.stream(AccessLevel.values())
      .collect(Collectors.toMap(AccessLevel::getValue, Function.identity()));

  public static AccessLevel fromName(final String name) {
    return names.get(name);
  }

  public static AccessLevel fromValue(final int value) {
    return values.get(value);
  }
}

대신 두 번째 매개 변수가 Collectors.toMap()되어야 Functions.identity()하지 null않습니까?
Adam Michalik 2015

예, 나는 null을 정체성으로 변환하는 guava와 함께 사용하는 도우미 클래스에서 이것을 채택했습니다.
John Meyer

이것은 Java 8의 새로운 기능을 깔끔하게 사용한 것입니다. 그러나 여전히 코드가 모든 열거 형에서 반복되어야 함을 의미하며 내 질문은 (구조적으로) 반복되는 상용구를 피하는 것이 었습니다.
sleske

5

org.apache.commons.lang.enums.ValuedEnum;

많은 상용구 코드를 작성하거나 각 Enum에 대한 코드를 복제하지 않기 위해 ValuedEnum대신 Apache Commons Lang을 사용했습니다.

정의 :

public class NRPEPacketType extends ValuedEnum {    
    public static final NRPEPacketType TYPE_QUERY = new NRPEPacketType( "TYPE_QUERY", 1);
    public static final NRPEPacketType TYPE_RESPONSE = new NRPEPacketType( "TYPE_RESPONSE", 2);

    protected NRPEPacketType(String name, int value) {
        super(name, value);
    }
}

용법:

int-> ValuedEnum :

NRPEPacketType packetType = 
 (NRPEPacketType) EnumUtils.getEnum(NRPEPacketType.class, 1);

좋은 생각입니다. 이것이 존재한다는 것을 몰랐습니다. 공유해 주셔서 감사합니다!
Keith P

3

아마도 다음과 같은 것을 사용할 수 있습니다.

interface EnumWithId {
    public int getId();

}


enum Foo implements EnumWithId {

   ...
}

그러면 유틸리티 클래스에서 반영 할 필요가 줄어 듭니다.


이 스 니펫을 사용하는 방법의 예를 제공 할 수 있습니까?
IgorGanapolsky

3

이 코드에서는 영구적이고 집중적 인 검색을 위해 사용할 메모리 또는 프로세스가 있고 변환기 배열을 인덱스로 사용하여 메모리를 선택합니다. 도움이 되었기를 바랍니다.

public enum Test{ 
VALUE_ONE(101, "Im value one"),
VALUE_TWO(215, "Im value two");
private final int number;
private final byte[] desc;

private final static int[] converter = new int[216];
static{
    Test[] st = values();
    for(int i=0;i<st.length;i++){
        cv[st[i].number]=i;
    }
}

Test(int value, byte[] description) {
    this.number = value;
    this.desc = description;
}   
public int value() {
    return this.number;
}
public byte[] description(){
    return this.desc;
}

public static String description(int value) {
    return values()[converter[rps]].desc;
}

public static Test fromValue(int value){
return values()[converter[rps]];
}
}

2

인터페이스를 사용하여 누가 보스인지 보여주세요.

public interface SleskeEnum {
    int id();

    SleskeEnum[] getValues();

}

public enum BonusType implements SleskeEnum {


  MONTHLY(1), YEARLY(2), ONE_OFF(3);

  public final int id;

  BonusType(int id) {
    this.id = id;
  }

  public SleskeEnum[] getValues() {
    return values();
  }

  public int id() { return id; }


}

public class Utils {

  public static SleskeEnum getById(SleskeEnum type, int id) {
      for(SleskeEnum t : type.getValues())
          if(t.id() == id) return t;
      throw new IllegalArgumentException("BonusType does not accept id " + id);
  }

  public static void main(String[] args) {

      BonusType shouldBeMonthly = (BonusType)getById(BonusType.MONTHLY,1);
      System.out.println(shouldBeMonthly == BonusType.MONTHLY);

      BonusType shouldBeMonthly2 = (BonusType)getById(BonusType.MONTHLY,1);
      System.out.println(shouldBeMonthly2 == BonusType.YEARLY);

      BonusType shouldBeYearly = (BonusType)getById(BonusType.MONTHLY,2);
      System.out.println(shouldBeYearly  == BonusType.YEARLY);

      BonusType shouldBeOneOff = (BonusType)getById(BonusType.MONTHLY,3);
      System.out.println(shouldBeOneOff == BonusType.ONE_OFF);

      BonusType shouldException = (BonusType)getById(BonusType.MONTHLY,4);
  }
}

그 결과 :

C:\Documents and Settings\user\My Documents>java Utils
true
false
true
true
Exception in thread "main" java.lang.IllegalArgumentException: BonusType does not accept id 4
        at Utils.getById(Utils.java:6)
        at Utils.main(Utils.java:23)

C:\Documents and Settings\user\My Documents>

1
Turd Ferguson의 대답과 마찬가지로, 그것은 제가 피하고 개선하고 싶은 불법적 인 해결책입니다 ...
sleske

일반적으로 id로 값을 요청할 때마다 values ​​()를 반복 할 필요가 없도록 static {} 블록에서 역 매핑을 만듭니다. 또한 일반적으로 valueOf (int) 메서드를 호출하여 Strings (OP 질문의 일부)에 대해 이미있는 valueOf (String) 메서드와 비슷하게 표시되도록합니다. Effective Java : tinyurl.com/4ffvc38의
Fredrik

@Sleske 더 세련된 솔루션으로 업데이트되었습니다. @Fredrik은 흥미롭지 만 반복이 중요한 문제가 될 것 같지 않습니다.
corsiKa

@glowcoder 글쎄요, 한 번 이상 반복 할 필요가 없다는 것은 매우 중요한 문제가 될 수있는 경우 초당 수천 번 수행하거나 두 번 호출하는 것이 중요하지 않다는 것을 의미합니다.
Fredrik

@Fredrik 나는 최적화가 필요할 때가 있다는 것을 인정할 것입니다. 또한 확인 된 성능 문제가 될 때까지 최적화하지 마십시오.
corsiKa

2

.ordinal()및 둘 다 values()[i]열거 형 순서에 종속되기 때문에 불안정합니다. 따라서 열거 형의 순서를 변경하거나 일부를 추가 / 삭제하면 프로그램이 중단됩니다.

enum과 int를 매핑하는 간단하면서도 효과적인 방법이 있습니다.

public enum Action {
    ROTATE_RIGHT(0), ROTATE_LEFT(1), RIGHT(2), LEFT(3), UP(4), DOWN(5);

    public final int id;
    Action(int id) {
        this.id = id;
    }

    public static Action get(int id){
        for (Action a: Action.values()) {
            if (a.id == id)
                return a;
        }
        throw new IllegalArgumentException("Invalid id");
    }
}

문자열에 적용하는 것은 어렵지 않습니다.


예, 저는 그렇게 할 수 있다는 것을 알고 있습니다. 모든 값을 반복하는 대신 역방향 조회를 위해 맵을 사용하는 것이 더 좋습니다. 나는 내 질문에서 이것을 언급했으며 각 열거 형에 상용구 코드를 사용하지 않기 위해 더 나은 솔루션을 찾고 있다고 언급했습니다.
sleske

2

Reverse Enum의 매우 깨끗한 사용 예

1 단계interface EnumConverter 정의

public interface EnumConverter <E extends Enum<E> & EnumConverter<E>> {
    public String convert();
    E convert(String pKey);
}

2 단계

클래스 이름 ReverseEnumMap 만들기

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

public class ReverseEnumMap<V extends Enum<V> & EnumConverter<V>> {
    private Map<String, V> map = new HashMap<String, V>();

    public ReverseEnumMap(Class<V> valueType) {
        for (V v : valueType.getEnumConstants()) {
            map.put(v.convert(), v);
        }
    }

    public V get(String pKey) {
        return map.get(pKey);
    }
}

3 단계

당신로 이동 Enum클래스와 implement그것과 EnumConverter<ContentType>물론 재정의 인터페이스 방법. 또한 정적 ReverseEnumMap을 초기화해야합니다.

public enum ContentType implements EnumConverter<ContentType> {
    VIDEO("Video"), GAME("Game"), TEST("Test"), IMAGE("Image");

    private static ReverseEnumMap<ContentType> map = new ReverseEnumMap<ContentType>(ContentType.class);

    private final String mName;

    ContentType(String pName) {
        this.mName = pName;
    }

    String value() {
        return this.mName;
    }

    @Override
    public String convert() {
        return this.mName;
    }

    @Override
    public ContentType convert(String pKey) {
        return map.get(pKey);
    }
}

4 단계

이제 생성 Communication클래스 파일과는 변환 할 수있는 새로운 방법의 부름 EnumStringStringEnum. 설명 목적으로 주요 방법을 넣었습니다.

public class Communication<E extends Enum<E> & EnumConverter<E>> {
    private final E enumSample;

    public Communication(E enumSample) {
        this.enumSample = enumSample;
    }

    public String resolveEnumToStringValue(E e) {
        return e.convert();
    }

    public E resolveStringEnumConstant(String pName) {
        return enumSample.convert(pName);
    }

//Should not put main method here... just for explanation purpose. 
    public static void main(String... are) {
        Communication<ContentType> comm = new Communication<ContentType>(ContentType.GAME);
        comm.resolveEnumToStringValue(ContentType.GAME); //return Game
        comm.resolveStringEnumConstant("Game"); //return GAME (Enum)
    }
}

자세한 설명을 보려면 클릭하십시오.


1
이것은 정말, 정말 좋아합니다. 저는 지금이 문제에 대한 확실한 해결책을 찾고있었습니다. 내가 만든 유일한 변경 사항은 ContentType convert(String pKey)정적 으로 만드는 것이 었는데 , 이는 Communication클래스 의 필요성을 제거하고 내 취향에 더 적합했습니다. +1
Chris Mantle

1

Java에서 동일한 지 확실하지 않지만 C의 열거 형 유형도 자동으로 정수로 매핑되므로 유형 또는 정수를 사용하여 액세스 할 수 있습니다. 아직 정수로 간단히 액세스 해 보셨습니까?


2
Java의 열거 형은 그렇게 작동하지 않습니다. 그들은 명시적인 유형입니다.
Chris Thompson

각 열거 형 개체에는 내부 번호 (즉, 선언 된 위치)가 있으며 .ordinal()메서드에서 액세스 할 수 있습니다 . (또는를 사용하십시오 BonusType.values()[i].) 그러나 위에 인용 된 예에서는 여기에있는 색인과 외부 값이 일치하지 않습니다.
Paŭlo Ebermann

1

정말 좋은 질문 :-) 언젠가 퍼거슨 씨와 비슷한 솔루션을 사용했습니다. 디 컴파일 된 열거 형은 다음과 같습니다.

final class BonusType extends Enum
{

    private BonusType(String s, int i, int id)
    {
        super(s, i);
        this.id = id;
    }

    public static BonusType[] values()
    {
        BonusType abonustype[];
        int i;
        BonusType abonustype1[];
        System.arraycopy(abonustype = ENUM$VALUES, 0, abonustype1 = new BonusType[i = abonustype.length], 0, i);
        return abonustype1;
    }

    public static BonusType valueOf(String s)
    {
        return (BonusType)Enum.valueOf(BonusType, s);
    }

    public static final BonusType MONTHLY;
    public static final BonusType YEARLY;
    public static final BonusType ONE_OFF;
    public final int id;
    private static final BonusType ENUM$VALUES[];

    static 
    {
        MONTHLY = new BonusType("MONTHLY", 0, 1);
        YEARLY = new BonusType("YEARLY", 1, 2);
        ONE_OFF = new BonusType("ONE_OFF", 2, 3);
        ENUM$VALUES = (new BonusType[] {
            MONTHLY, YEARLY, ONE_OFF
        });
    }
}

이것을 보는 것이 왜 ordinal()불안정한 지 분명 합니다. 그것은이다 i에서 super(s, i);. 나는 또한 당신이 이미 열거 한 것보다 더 우아한 해결책을 생각할 수 있다는 비관적이다. 모든 열거 형은 최종 클래스와 같은 클래스입니다.


1

완전성을 위해 모든 열거 형 유형에서 인덱스별로 열거 형 값을 검색하는 일반적인 방법은 다음과 같습니다. 내 의도는 메서드를 Enum.valueOf (Class, String) 처럼 보이고 느끼도록 만드는 것이 었습니다 . 참고로 여기 에서이 방법을 복사했습니다 .

인덱스 관련 문제 (이미 여기서 자세히 논의 됨)는 여전히 적용됩니다.

/**
 * Returns the {@link Enum} instance for a given ordinal.
 * This method is the index based alternative
 * to {@link Enum#valueOf(Class, String)}, which
 * requires the name of an instance.
 * 
 * @param <E> the enum type
 * @param type the enum class object
 * @param ordinal the index of the enum instance
 * @throws IndexOutOfBoundsException if ordinal < 0 || ordinal >= enums.length
 * @return the enum instance with the given ordinal
 */
public static <E extends Enum<E>> E valueOf(Class<E> type, int ordinal) {
    Preconditions.checkNotNull(type, "Type");
    final E[] enums = type.getEnumConstants();
    Preconditions.checkElementIndex(ordinal, enums.length, "ordinal");
    return enums[ordinal];
}

이것은 할당 된 정수 ID가 아닌 서 수로 만 열거 형 값을 검색하기 때문에 내가 찾고있는 것이 아닙니다 (제 질문 참조). 또한 원하는 경우 MyEnumType.values()정적 도우미 메서드를 사용할 필요가 없습니다.
sleske

0
Int -->String :

public enum Country {

    US("US",0),
    UK("UK",2),
    DE("DE",1);


    private static Map<Integer, String> domainToCountryMapping; 
    private String country;
    private int domain;

    private Country(String country,int domain){
        this.country=country.toUpperCase();
        this.domain=domain;
    }

    public String getCountry(){
        return country;
    }


    public static String getCountry(String domain) {
        if (domainToCountryMapping == null) {
            initMapping();
        }

        if(domainToCountryMapping.get(domain)!=null){
            return domainToCountryMapping.get(domain);
        }else{
            return "US";
        }

    }

     private static void initMapping() {
         domainToCountryMapping = new HashMap<Integer, String>();
            for (Country s : values()) {
                domainToCountryMapping.put(s.domain, s.country);
            }
        }

0

일반적인 접근 방식을 사용하고 싶었 기 때문에 다른 것이 필요했습니다. 열거 형과 바이트 배열을 읽고 있습니다. 이것이 내가 생각하는 곳입니다.

public interface EnumConverter {
    public Number convert();
}



public class ByteArrayConverter {
@SuppressWarnings("unchecked")
public static Enum<?> convertToEnum(byte[] values, Class<?> fieldType, NumberSystem numberSystem) throws InvalidDataException {
    if (values == null || values.length == 0) {
        final String message = "The values parameter must contain the value";
        throw new IllegalArgumentException(message);
    }

    if (!dtoFieldType.isEnum()) {
        final String message = "dtoFieldType must be an Enum.";
        throw new IllegalArgumentException(message);
    }

    if (!EnumConverter.class.isAssignableFrom(fieldType)) {
        final String message = "fieldType must implement the EnumConverter interface.";
        throw new IllegalArgumentException(message);
    }

    Enum<?> result = null;
    Integer enumValue = (Integer) convertToType(values, Integer.class, numberSystem); // Our enum's use Integer or Byte for the value field.

    for (Object enumConstant : fieldType.getEnumConstants()) {
        Number ev = ((EnumConverter) enumConstant).convert();

        if (enumValue.equals(ev)) {
            result = (Enum<?>) enumConstant;
            break;
        }
    }

    if (result == null) {
        throw new EnumConstantNotPresentException((Class<? extends Enum>) fieldType, enumValue.toString());
    }

    return result;
}

public static byte[] convertEnumToBytes(Enum<?> value, int requiredLength, NumberSystem numberSystem) throws InvalidDataException {
    if (!(value instanceof EnumConverter)) {
        final String message = "dtoFieldType must implement the EnumConverter interface.";
        throw new IllegalArgumentException(message);
    }

    Number enumValue = ((EnumConverter) value).convert();
    byte[] result = convertToBytes(enumValue, requiredLength, numberSystem);
    return result;
}

public static Object convertToType(byte[] values, Class<?> type, NumberSystem numberSystem) throws InvalidDataException {
    // some logic to convert the byte array supplied by the values param to an Object.
}

public static byte[] convertToBytes(Object value, int requiredLength, NumberSystem numberSystem) throws InvalidDataException {
    // some logic to convert the Object supplied by the'value' param to a byte array.
}
}

열거 형의 예 :

public enum EnumIntegerMock implements EnumConverter {
    VALUE0(0), VALUE1(1), VALUE2(2);

    private final int value;

    private EnumIntegerMock(int value) {
        this.value = value;
    }

public Integer convert() {
    return value;
}

}

public enum EnumByteMock implements EnumConverter {
    VALUE0(0), VALUE1(1), VALUE2(2);

    private final byte value;

    private EnumByteMock(int value) {
        this.value = (byte) value;
    }

    public Byte convert() {
        return value;
    }
}

0

수락 된 답변이 자체 포함되지 않기 때문에 :

지원 코드 :

public interface EnumWithCode<E extends Enum<E> & EnumWithCode<E>> {

    public Integer getCode();

    E fromCode(Integer code);
}


public class EnumWithCodeMap<V extends Enum<V> & EnumWithCode<V>> {

    private final HashMap<Integer, V> _map = new HashMap<Integer, V>();

    public EnumWithCodeMap(Class<V> valueType) {
        for( V v : valueType.getEnumConstants() )
            _map.put(v.getCode(), v);
    }

    public V get(Integer num) {
        return _map.get(num);
    }
}

사용 예 :

public enum State implements EnumWithCode<State> {
    NOT_STARTED(0), STARTED(1), ENDED(2);

    private static final EnumWithCodeMap<State> map = new EnumWithCodeMap<State>(
            State.class);

    private final int code;

    private State(int code) {
        this.code = code;
    }

    @Override
    public Integer getCode() {
        return code;
    }

    @Override
    public State fromCode(Integer code) {
        return map.get(code);
    }

}

0

주어진:

public enum BonusType {MONTHLY (0), YEARLY (1), ONE_OFF (2)}

BonusType 보너스 = YEARLY;

System.out.println (bonus.Ordinal () + ":"+ 보너스)

산출 : 1 : YEARLY


0

클래스 카가있는 경우

public class Car {
    private Color externalColor;
}

그리고 속성 Color 는 클래스입니다.

@Data
public class Color {
    private Integer id;
    private String name;
}

그리고 Color 를 Enum 으로 변환하고 싶습니다.

public class CarDTO {
    private ColorEnum externalColor;
}

간단히에 메소드를 추가 색상 변환 클래스 색상ColorEnum

@Data
public class Color {
    private Integer id;
    private String name;

    public ColorEnum getEnum(){
        ColorEnum.getById(id);
    }
}

ColorEnum 내부에서 getById () 메소드를 구현합니다.

public enum ColorEnum {
...
    public static ColorEnum getById(int id) {
        for(ColorEnum e : values()) {
            if(e.id==id) 
                return e;
        }
    }
}

이제 classMap을 사용할 수 있습니다.

private MapperFactory factory = new DefaultMapperFactory.Builder().build();
...
factory.classMap(Car.class, CarDTO.class)
    .fieldAToB("externalColor.enum","externalColor")
    .byDefault()
    .register();
...
CarDTO dto = mapper.map(car, CarDTO.class);
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.