次の列挙型を指定して、Java で Int を列挙型にキャストする正しい方法は何ですか?
public enum MyEnum
{
EnumValue1,
EnumValue2
}
MyEnum enumValue = (MyEnum) x; //Doesn't work???
または、つまり、その列挙型の有効な序数である必要があるMyEnum.values()[x]
場所を試してください。x
0
1
int
Java では列挙型は実際にはクラスであり (したがって、列挙型の値はオブジェクトです)、列挙型にまたはをキャストできないことに注意してくださいInteger
。
MyEnum.values()[x]
高価な操作です。パフォーマンスが問題になる場合は、次のようにすることをお勧めします。
public enum MyEnum {
EnumValue1,
EnumValue2;
public static MyEnum fromInteger(int x) {
switch(x) {
case 0:
return EnumValue1;
case 1:
return EnumValue2;
}
return null;
}
}
整数値を与えたい場合は、以下のような構造を使用できます
public enum A
{
B(0),
C(10),
None(11);
int id;
private A(int i){id = i;}
public int GetID(){return id;}
public boolean IsEmpty(){return this.equals(A.None);}
public boolean Compare(int i){return id == i;}
public static A GetValue(int _id)
{
A[] As = A.values();
for(int i = 0; i < As.length; i++)
{
if(As[i].Compare(_id))
return As[i];
}
return A.None;
}
}
値をキャッシュし、単純な静的アクセス メソッドを作成します。
public static enum EnumAttributeType {
ENUM_1,
ENUM_2;
private static EnumAttributeType[] values = null;
public static EnumAttributeType fromInt(int i) {
if(EnumAttributeType.values == null) {
EnumAttributeType.values = EnumAttributeType.values();
}
return EnumAttributeType.values[i];
}
}
Java 列挙型には、C++ で行うのと同じ種類の列挙型から int へのマッピングがありません。
つまり、すべての列挙型にvalues
は可能な列挙値の配列を返すメソッドがあるため、
MyEnum enumValue = MyEnum.values()[x];
動作するはずです。少し面倒なので、可能であればint
s からEnum
s (またはその逆) に変換しようとしないほうがよいかもしれません。
これは通常行われることではないので、再考します。しかし、そうは言っても、基本的な操作は int --> enum using EnumType.values()[intNum]
、および enum --> int usingenumInst.ordinal()
です。
ただし、 の実装にvalues()
は配列のコピーを提供する以外に選択肢がないため (Java 配列は読み取り専用ではありません)、 を使用しEnumMap
て enum --> int マッピングをキャッシュすることをお勧めします。
使用するMyEnum enumValue = MyEnum.values()[x];
これが私が行く予定の解決策です。これは、連続していない整数で機能するだけでなく、列挙値の基になる id として使用したい他のデータ型でも機能するはずです。
public Enum MyEnum {
THIS(5),
THAT(16),
THE_OTHER(35);
private int id; // Could be other data type besides int
private MyEnum(int id) {
this.id = id;
}
public int getId() {
return this.id;
}
public static Map<Integer, MyEnum> buildMap() {
Map<Integer, MyEnum> map = new HashMap<Integer, MyEnum>();
MyEnum[] values = MyEnum.values();
for (MyEnum value : values) {
map.put(value.getId(), value);
}
return map;
}
}
特定の時間 (ファイルからデータをロードするとき) に ID を列挙型に変換する必要があるだけなので、マップを常にメモリに保持する必要はありません。常にマップにアクセスできるようにする必要がある場合は、常に Enum クラスの静的メンバーとしてマップをキャッシュできます。
これは医者と同じ答えですが、可変配列の問題を解消する方法を示しています。最初に分岐予測のためにこの種のアプローチを使用する場合、効果はほとんどまたはゼロであり、コード全体で可変配列 values() 関数を 1 回だけ呼び出します。両方の変数が静的であるため、この列挙を使用するたびに n * メモリも消費しません。
private static boolean arrayCreated = false;
private static RFMsgType[] ArrayOfValues;
public static RFMsgType GetMsgTypeFromValue(int MessageID) {
if (arrayCreated == false) {
ArrayOfValues = RFMsgType.values();
}
for (int i = 0; i < ArrayOfValues.length; i++) {
if (ArrayOfValues[i].MessageIDValue == MessageID) {
return ArrayOfValues[i];
}
}
return RFMsgType.UNKNOWN;
}
適切なオプションは、からへの変換を避けることです。たとえば、最大値が必要な場合は、 x.ordinal() を y.ordinal() と比較して、それに応じて x または y を返すことができます。(このような比較を意味のあるものにするために、値の順序を変更する必要がある場合があります。)int
enum
それが不可能な場合はMyEnum.values()
、静的配列に格納します。
enum MyEnum {
A(0),
B(1);
private final int value;
private MyEnum(int val) {this.value = value;}
private static final MyEnum[] values = MyEnum.values();//cache for optimization
public static final getMyEnum(int value) {
try {
return values[value];//OOB might get triggered
} catch (ArrayOutOfBoundsException e) {
} finally {
return myDefaultEnumValue;
}
}
}