유한 한 수의 값만 취할 수있는 변수 / 매개 변수로 작업 할 때 다음과 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 에 넣은 다음이를 캐시하여 조회에 사용합니다. 작동하지만이 메서드를 사용하는 각 열거 형에 동일하게 복사해야합니다. :-(.- 조회 메소드를 정적 유틸리티 클래스에 넣으십시오. 그런 다음 하나의 “조회”메서드 만 필요하지만 임의의 열거 형에 대해 작동하려면 리플렉션을 사용하여 조작해야합니다.
두 가지 방법 모두 이러한 간단한 (?) 문제에 대해 매우 어색해 보입니다.
다른 아이디어 / 통찰이 있습니까?
답변
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 인터페이스를 상속한다는 사실을 기반으로하기 때문에 ‘반사 처리’가 필요하지 않습니다.
답변
열거 형 → 정수
yourEnum.ordinal()
int → 열거 형
EnumType.values()[someInt]
문자열 → 열거 형
EnumType.valueOf(yourString)
열거 형 → 문자열
yourEnum.name()
참고 :
올바르게 지적했듯이 ordinal()
버전마다 “불안정”할 수 있습니다. 이것이 내가 항상 데이터베이스에 문자열로 상수를 저장하는 정확한 이유입니다. (실제로 MySql을 사용할 때 MySql 열거 형 으로 저장합니다 !)
답변
나는 이것을 웹에서 발견했고, 구현하기 매우 유용하고 간단했습니다. 이 솔루션은 내가 만든 것이 아닙니다.
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);
}
}
답변
이 질문에 대한 답변은 Java 8 릴리스와 함께 구식입니다.
- 서수는 데이터베이스와 같은 JVM 외부에서 지속되는 경우 불안정하므로 서수를 사용하지 마십시오.
- 키 값으로 정적지도를 만드는 것은 비교적 쉽습니다.
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);
}
}
답변
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);
답변
아마도 다음과 같은 것을 사용할 수 있습니다.
interface EnumWithId {
public int getId();
}
enum Foo implements EnumWithId {
...
}
그러면 유틸리티 클래스에서 반영 할 필요가 줄어 듭니다.
답변
이 코드에서는 영구적이고 집중적 인 검색을 위해 사용할 메모리 또는 프로세스가 있고 변환기 배열을 인덱스로 사용하여 메모리를 선택합니다. 도움이 되었기를 바랍니다.
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]];
}
}