열거 서수에서 열거 형식으로 변환
열거형이 있습니다.ReportTypeEnum
모든 클래스의 메서드 간에 전달되지만 URL에 전달해야 하므로 서수 메서드를 사용하여 int 값을 가져옵니다.다른 JSP 페이지에서 취득한 후, 그것을 다시 R&D로 변환해야 합니다.ReportTypeEnum
계속 패스할 수 있게.
서수를 로 변환하려면 어떻게 해야 합니까?ReportTypeEnum
?
Java 6 SE 사용.
서수를 열거형으로 변환하려면 다음을 수행합니다.
ReportTypeEnum value = ReportTypeEnum.values()[ordinal];
어레이의 경계에 주의해 주세요.
에의 모든 콜은values()
는 퍼포먼스에 부정적인 영향을 줄 수 있는 새로 복제된 어레이를 반환합니다.어레이가 자주 호출되는 경우 어레이를 캐시할 수 있습니다.
이 답변은 코멘트에 피드백이 포함되도록 편집되었습니다.
이것은 거의 확실히 나쁜 생각이다.확실히 서수가 사실상의 영속적인 경우(예를 들어 누군가가 URL을 북마크했기 때문에) - 이는 사용자가 항상 다음을 유지해야 함을 의미합니다.enum
향후의 주문은, 코드 유지 보수업자에게는 명확하지 않을지도 모릅니다.
를 부호화하지 않는 이유는 무엇입니까?enum
사용.myEnumValue.name()
(및 디코딩을 통해ReportTypeEnum.valueOf(s)
대신?
만약 내가 그것을 사용할 예정이라면values()
많은 것:
enum Suit {
Hearts, Diamonds, Spades, Clubs;
public static final Suit values[] = values();
}
한편, where.java:
Suit suit = Suit.values[ordinal];
어레이를 비공개로 하고 싶은 경우는, 다음의 순서에 따릅니다.
private static final Suit values[] = values();
public static Suit get(int ordinal) { return values[ordinal]; }
...
Suit suit = Suit.get(ordinal);
어레이의 경계에 주의해 주세요.
나는 서수를 사용하는 것이 아마도 나쁜 생각일 것이라는 대부분의 사람들의 의견에 동의한다.이 문제를 해결하려면 보통 DB 값을 가져와서 스태틱을 생성할 수 있는 개인 생성자를 enum에 지정합니다.fromDbValue
Jan의 답변과 유사한 기능을 합니다.
public enum ReportTypeEnum {
R1(1),
R2(2),
R3(3),
R4(4),
R5(5),
R6(6),
R7(7),
R8(8);
private static Logger log = LoggerFactory.getLogger(ReportEnumType.class);
private static Map<Integer, ReportTypeEnum> lookup;
private Integer dbValue;
private ReportTypeEnum(Integer dbValue) {
this.dbValue = dbValue;
}
static {
try {
ReportTypeEnum[] vals = ReportTypeEnum.values();
lookup = new HashMap<Integer, ReportTypeEnum>(vals.length);
for (ReportTypeEnum rpt: vals)
lookup.put(rpt.getDbValue(), rpt);
}
catch (Exception e) {
// Careful, if any exception is thrown out of a static block, the class
// won't be initialized
log.error("Unexpected exception initializing " + ReportTypeEnum.class, e);
}
}
public static ReportTypeEnum fromDbValue(Integer dbValue) {
return lookup.get(dbValue);
}
public Integer getDbValue() {
return this.dbValue;
}
}
이제 룩업을 변경하지 않고 순서를 변경할 수 있습니다.또, 그 반대의 경우도 마찬가지입니다.
스태틱 룩업테이블을 사용할 수 있습니다.
public enum Suit {
spades, hearts, diamonds, clubs;
private static final Map<Integer, Suit> lookup = new HashMap<Integer, Suit>();
static {
int ordinal = 0;
for (Suit suit : EnumSet.allOf(Suit.class)) {
lookup.put(ordinal, suit);
ordinal+= 1;
}
}
public Suit fromOrdinal(int ordinal) {
return lookup.get(ordinal);
}
}
이게 제가 쓰는 거예요.위의 단순한 솔루션보다 훨씬 덜 효율적이라고 주장하지는 않습니다.위의 솔루션에서 잘못된 서수 값이 사용되었을 때 ArrayIndexOutOfBounds보다 훨씬 명확한 예외 메시지가 나타납니다.
또한 EnumSet javadoc이 반복자가 원래 순서대로 요소를 반환하도록 지정한다는 사실을 활용합니다.그게 틀렸다면 단언할 수 있어요.
JUnit4 테스트는 사용법을 보여줍니다.
/**
* convert ordinal to Enum
* @param clzz may not be null
* @param ordinal
* @return e with e.ordinal( ) == ordinal
* @throws IllegalArgumentException if ordinal out of range
*/
public static <E extends Enum<E> > E lookupEnum(Class<E> clzz, int ordinal) {
EnumSet<E> set = EnumSet.allOf(clzz);
if (ordinal < set.size()) {
Iterator<E> iter = set.iterator();
for (int i = 0; i < ordinal; i++) {
iter.next();
}
E rval = iter.next();
assert(rval.ordinal() == ordinal);
return rval;
}
throw new IllegalArgumentException("Invalid value " + ordinal + " for " + clzz.getName( ) + ", must be < " + set.size());
}
@Test
public void lookupTest( ) {
java.util.concurrent.TimeUnit tu = lookupEnum(TimeUnit.class, 3);
System.out.println(tu);
}
안전 제일주의(Kotlin 사용):
// Default to null
EnumName.values().getOrNull(ordinal)
// Default to a value
EnumName.values().getOrElse(ordinal) { EnumName.MyValue }
Proguard를 탑재한 Android에서는 다음과 같이 동작합니다.
public enum SomeStatus {
UNINITIALIZED, STATUS_1, RESERVED_1, STATUS_2, RESERVED_2, STATUS_3;//do not change order
private static SomeStatus[] values = null;
public static SomeStatus fromInteger(int i) {
if(SomeStatus.values == null) {
SomeStatus.values = SomeStatus.values();
}
if (i < 0) return SomeStatus.values[0];
if (i >= SomeStatus.values.length) return SomeStatus.values[0];
return SomeStatus.values[i];
}
}
짧아서 Proguard에서 예외를 둘 염려가 없습니다.
다음과 같은 간단한 방법을 정의할 수 있습니다.
public enum Alphabet{
A,B,C,D;
public static Alphabet get(int index){
return Alphabet.values()[index];
}
}
사용법은 다음과 같습니다.
System.out.println(Alphabet.get(2));
public enum Suit implements java.io.Serializable, Comparable<Suit>{
spades, hearts, diamonds, clubs;
private static final Suit [] lookup = Suit.values();
public Suit fromOrdinal(int ordinal) {
if(ordinal< 1 || ordinal> 3) return null;
return lookup[value-1];
}
}
시험반
public class MainTest {
public static void main(String[] args) {
Suit d3 = Suit.diamonds;
Suit d3Test = Suit.fromOrdinal(2);
if(d3.equals(d3Test)){
System.out.println("Susses");
}else System.out.println("Fails");
}
}
보다 효율적인 코드가 있으면 공유해 주셔서 감사합니다.내 enum은 크고 수천 번 계속 호출됩니다.
한 것입니다.ExampleEnum valueOfOrdinal = ExampleEnum.values()[ordinal];
하지만 앞서 언급한 바와 같이 이 방법은 쉽고 효과적입니다.ExampleEnum.values()
는 모든 콜에 대해 새로운 클론된 어레이를 반환합니다.이치노력하다할 수 .ExampleEnum[] values = values()
캐시된 어레이를 변경하는 것도 위험합니다. 쓸 수 ExampleEnum.values[0] = ExampleEnum.type2;
따라서 추가 복사를 하지 않는 접근기 방식으로 비공개로 하겠습니다.
private enum ExampleEnum{
type0, type1, type2, type3;
private static final ExampleEnum[] values = values();
public static ExampleEnum value(int ord) {
return values[ord];
}
}
사용할 수 있습니다.ExampleEnum.value(ordinal)
된 열거치를 ordinal
모든 열거형에는 name()이 있습니다.이것에 의해, 열거형 멤버의 이름을 가지는 문자열이 지정됩니다.
의 「」enum Suit{Heart, Spade, Club, Diamond}
,Suit.Heart.name()
주다Heart
.
열거형에는 ""가 .valueOf()
및합니다.
Enum.valueOf(Suit.class, "Heart")
Suit.Heart
.
왜 누가 서수를 쓰는지 모르겠다.다른 개발자가 일부 코드가 서수 값에 의존하고 있다는 것을 알지 못하기 때문에 nanoseconds는 빨라질 수 있지만, enum 멤버가 변경되면 안전하지 않습니다(특히 질문에서 인용된 JSP 페이지에서는 네트워크와 데이터베이스의 오버헤드가 정수를 사용하지 않고 시간을 완전히 지배하고 있습니다).
언급URL : https://stackoverflow.com/questions/609860/convert-from-enum-ordinal-to-enum-type
'IT이야기' 카테고리의 다른 글
JPA와 휴지 상태를 사용할 때 JOIN과 JOIN FETCH의 차이점은 무엇입니까? (0) | 2022.05.29 |
---|---|
데이터 구조가 "침입적"이라는 것은 무엇을 의미합니까? (0) | 2022.05.29 |
메서드 인수에 Not Null 주석 사용 (0) | 2022.05.29 |
Vue.js - Vuex: 모듈스토어를 도우미 파일로 Import할 때 액션이 디스패치되는 이유는 무엇입니까? (0) | 2022.05.29 |
돌연변이를 사용하지 않고 Vuex 상태를 직접 변환합니다. (0) | 2022.05.29 |