マップでの一般的な列挙型クラスを使用します

xZise:

私は彼らの列挙クラスにクラス名のマップを持っているし、私のような文字列を解析する方法持っている"SomeEnum.FIRST"実際のオブジェクトにします。しかし、Enum.valueOf受け入れないClass<? extends Enum<?>>マップを格納することはできませんしながらClass<T extends Enum<T>>

コードの場合、マップは次のようになります。

    private static final HashMap<String, Class<? extends Enum<?>>> enumsMap;

    static {
        enumsMap = new HashMap<>();
        // These are two DIFFERENT enum classes!
        registerEnum(SomeEnum.class);
        registerEnum(AnotherEnum.class);
    }

    private static void registerEnum(Class<? extends Enum<?>> enumClass) {
        enumsMap.put(enumClass.getSimpleName(), enumClass);
    }

そして、ここでパーサ(削除不要なコード)は、次のとおりです。

    public <T extends Enum<T>> Object[] parse(List<String> strParameters) {
        Object[] parameters = new Object[strParameters.size()];
        for (int i = 0; i < parameters.length; i++) {
            String strParameter = strParameters.get(i);
            int delim = strParameter.lastIndexOf('.');
            String className = strParameter.substring(0, delim - 1);
            String enumName = strParameter.substring(delim + 1);
            Class<T> enumClass = (Class<T>) enumsMap.get(className);
            parameters[i] = Enum.valueOf(enumClass, enumName);
        }
        return parameters;
    }

私はこれを呼び出す場合、今parse、私のIDE(アンドロイドStudioは)、その「未チェックの方法『解析(一覧)』呼び出し」を私に語った、これはそのせいでジェネリック型である私の知る限り。私はそれを削除した場合parse、それがコンパイルされないだろうが、警告が消えます。その周りに良いの方法はありますか?

ジョシュア・テイラー:

あなたのような列挙型を使用している場合:

  enum Foo {
    A, B, C
  }

  enum Bar {
    D, E, F
  }

そして、あなたは以下のコードと話しているマップの種類を実装することができます。

class MyEnums {
    private final Map<String, Class<? extends Enum<?>>> map = new HashMap<>();

    public void addEnum(Class<? extends Enum<?>> e) {
      map.put(e.getSimpleName(), e);
    }

    private <T extends Enum<T>> T parseUnsafely(String name) {
      final int split = name.lastIndexOf(".");
      final String enumName = name.substring(0, split);
      final String memberName = name.substring(split + 1);
      @SuppressWarnings("unchecked")
      Class<T> enumType = (Class<T>) map.get(enumName);
      return Enum.valueOf(enumType, memberName);
    }

    public Object parse(String name) {
      return parseUnsafely(name);
    }

    public Object[] parseAll(String... names) {
      return Stream.of(names)
          .map(this::parse)
          .collect(toList())
          .toArray();
    }
  }

これがないではないものの、未チェックのキャストを回避します。それだけで一時的にあなたからそれを隠します。どこどこで見ることができますSuppressWarningsについての警告を消音するために使用されますenumTypeこれは、できるだけ範囲を限定されるものとしてで警告抑制を適用することが一般的に良い習慣です。この場合、それはその単一代入のためです。これは、一般的に赤い旗可能性がありますが、本例では、我々は、彼らがで追加されていなければならないので、マップ内の値のみが、実際には、列挙型クラスであることを知っていますaddEnum

その後、それは次のように使用することができます。

  MyEnums me = new MyEnums();
  me.addEnum(Foo.class);
  me.addEnum(Bar.class);
  System.out.println(me.parse("Foo.A"));
  System.out.println(me.parse("Bar.E"));
  System.out.println(Arrays.toString(me.parseAll("Foo.B", "Bar.D", "Foo.C")));

これは版画:

A
E
[B, D, C]

あなたは、私が破ったことに気づくでしょうparseUnsafelyし、parse別のメソッドに。我々は公開したくないという理由parseUnsafelyで直接には、それは我々が実際に施行することができないことをその戻り値の型が保証を行っていることです。それがさらされた場合には、我々のようなコードを書くことができ

Bar bar = me.parseUnsafely("Foo.B");

これはコンパイルが、キャストクラスの例外を除いて、実行時に失敗します。

おすすめ

転載: http://43.154.161.224:23101/article/api/json?id=187109&siteId=1