2

このコードでは、コンパイラ エラーが発生します。コメントを参照してください。

 public enum Type {
   CHANGESET("changeset"),
   NEW_TICKET("newticket"),
   TICKET_CHANGED("editedticket"),
   CLOSED_TICKET("closedticket");

   private static final Map<String, Type> tracNameMap = new HashMap<String, Type>();

   private Type(String name) {
    tracNameMap.put(name, this); // cannot refer to static field within an initializer
   }

   public static Type getByTracName(String tn) {
    return tracNameMap.get(tracNameMap);
   }

  }

フィールドの1つから列挙値を取得して、これを機能させる方法はありMapますか?

4

5 に答える 5

9

マップはおそらくここでやり過ぎです。5 つ以上の enum 値を持つことを計画していない限り、有効な文字列を反復処理して正しい文字列を返すだけで getByTracName(String tn) を実装できます。マップキーが常に列挙名である場合は、次のことができます。

public enum Type {
CHANGESET,
NEW_TICKET,
TICKET_CHANGED,
CLOSED_TICKET;

private static final Map<String, Type> tracNameMap = new HashMap<String, Type>();
static {
    for (Type t:Type.values()) {
        tracNameMap.put(t.name(), t);
    }
}
public static Type getByTracName(String tn) {
    return tracNameMap.get(tracNameMap);
}

}

またはあなたが行うことができます:

public static Type getByTracName(String tn) {
  return Enum.valueOf(Type.class,tn);
}
于 2010-11-25T15:20:41.193 に答える
7

はぁ、おかしい!ほんの数日前、私はこれに出くわしました。

Java言語仕様、第3版、セクション8.9から:

コンストラクター、インスタンス初期化ブロック、またはそのタイプのインスタンス変数初期化式から、コンパイル時定数(§15.28)ではない列挙型の静的フィールドを参照することは、コンパイル時エラーです。列挙型定数eのコンストラクター、インスタンス初期化ブロック、またはインスタンス変数初期化子式が、それ自体またはeの右側に宣言されている同じタイプの列挙型定数を参照するのはコンパイル時エラーです。

討論

このルールがないと、列挙型に固有の初期化の循環性のために、明らかに妥当なコードが実行時に失敗します。(循環性は、「自己型」静的フィールドを持つすべてのクラスに存在します。)失敗するコードの種類の例を次に示します。

enum Color {
        RED, GREEN, BLUE;
        static final Map<String,Color> colorMap = 
        new HashMap<String,Color>();
        Color() {
            colorMap.put(toString(), this);
        }
    } 

この列挙型の静的初期化では、列挙型定数のコンストラクターの実行時に静的変数colorMapが初期化されないため、NullPointerExceptionがスローされます。上記の制限により、そのようなコードはコンパイルされません。

この例は、正しく機能するように簡単にリファクタリングできることに注意してください。

enum Color {
        RED, GREEN, BLUE;
        static final Map<String,Color> colorMap = 
        new HashMap<String,Color>();
        static {
            for (Color c : Color.values())
                colorMap.put(c.toString(), c);
        }
    } 

静的初期化は上から下に行われるため、リファクタリングされたバージョンは明らかに正しいです。

于 2010-12-12T00:26:53.007 に答える
2

私はリバーシブル列挙型パターンを使用します:

ReversibleEnum.java

/**
 * <p>
 * This interface defines the method that the {@link Enum} implementations
 * should implement if they want to have the reversible lookup functionality.
 * i.e. allow the lookup using the code for the {@link Enum} constants.
 * </p>
 * @author Atif Khan
 * @param < E >
 *          The value of Enum constant
 * @param < V >
 *          The Enum constant to return from lookup
 */
public interface ReversibleEnum< E, V >
{
  /**
   * <p>
   * Return the value/code of the enum constant.
   * </p>
   * @return value
   */
  public E getValue();

  /**
   * <p>
   * Get the {@link Enum} constant by looking up the code in the reverse enum
   * map.
   * </p>
   * @param  E - code
   * @return V - The enum constant
   */
  public V reverse( E code );
}

逆EnumMap.java

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

/**
 * <p>
 * A utility class that provides a reverse map of the {@link Enum} that is keyed
 * by the value of the {@link Enum} constant.
 * </p>
 * @author Atif Khan
 * @param < K >
 *          The class type of the value of the enum constant
 * @param < V >
 *          The Enum for which the map is being created
 */
public class ReverseEnumMap< K, V extends ReversibleEnum< K, V >>
{
  private final Map< K, V > mReverseMap = new HashMap< K, V >();

  /**
   * <p>
   * Create a new instance of ReverseEnumMap.
   * </p>
   * @param valueType
   */
  public ReverseEnumMap( final Class< V > valueType )
  {
    for( final V v : valueType.getEnumConstants() ) {
      mReverseMap.put( v.getValue(), v );
    }
  }

  /**
   * <p>
   * Perform the reverse lookup for the given enum value and return the enum
   * constant.
   * </p>
   * @param enumValue
   * @return enum constant
   */
  public V get( final K enumValue )
  {
    return mReverseMap.get( enumValue );
  }
}

Type.java を次のように変更します。

public enum Type implements ReversibleEnum< String, Type >  {
  CHANGESET( "changeset" ),
  NEW_TICKET( "new" ),
  TICKET_CHANGED( "changed" ),
  CLOSED_TICKET( "closed" );

  private String mValue;  

  private static final ReverseEnumMap< String, Type > mReverseMap = new ReverseEnumMap< String, Type >( Type.class );  

  Type(final String value)   
  {  
    mValue = value;  
  }  

  public final String getValue()   
  {  
    return mValue;  
  }  

  public Type reverse( final String value )  
  {  
    return mReverseMap.get( value );  
  } 
} 
于 2010-11-25T15:55:32.130 に答える
1

これはどう; エラーが発生しやすい IMO のような 2 つの場所でコードを変更する必要はありません。

enum Type {

    CHANGESET("changeset"),
    NEW_TICKET("newticket"),
    TICKET_CHANGED("editedticket"),
    CLOSED_TICKET("closedticket");

    private static final Map<String, Type> tracNameMap =
                                      new HashMap<String, Type>();

    private final String name;

    public Type typeForName(final String name) {
        if (tracNameMap.containsKey(name)) {
            return tracNameMap.get(name);
        } else {
            for (final Type t : Type.values()) {
                if (t.name.equals(name)) {
                    tracNameMap.put(name, t);
                    return t;
                }
            }
            throw new IllegalArgumentException("Invalid enum name");
        }
    }

    private Type(String name) {
        this.name = name;
    }

}
于 2010-11-25T16:08:53.143 に答える
0

すべての列挙値を繰り返す必要がありますが、私自身の回避策:

    public enum Type {
        CHANGESET,
        NEW_TICKET,
        TICKET_CHANGED,
        CLOSED_TICKET;

        private static final Map<String, Type> tracNameMap = new HashMap<String, Type>();
        static {
            tracNameMap.put("changeset", CHANGESET);
            tracNameMap.put("newticket", NEW_TICKET);
            tracNameMap.put("editedticket", TICKET_CHANGED);
            tracNameMap.put("closedticket", CLOSED_TICKET);
        }
        public static Type getByTracName(String tn) {
            return tracNameMap.get(tracNameMap);
        }

    }
于 2010-11-25T15:08:52.953 に答える