Utilizar las clases de enumeración genéricos en los mapas

xZise:

Tengo un mapa de nombres de clase a su clase de enumeración y tengo método que analiza una cadena como "SomeEnum.FIRST"en el objeto real. Pero Enum.valueOfno acepta Class<? extends Enum<?>>mientras que el mapa no se puede almacenar Class<T extends Enum<T>>.

Para el código, el mapa se ve algo como esto:

    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);
    }

Y aquí está el analizador (código innecesario eliminado):

    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;
    }

Y ahora si esto lo llamo parse, mi IDE (Estudio Android) me dice, que "no facturado método 'parse (Lista)' invocación", y que yo sepa esto es debido a que el tipo genérico. Si quito en parse, no sería compilar pero desaparece la advertencia. ¿Hay una buena manera de evitarlo?

Joshua Taylor:

Si tiene enumeraciones como:

  enum Foo {
    A, B, C
  }

  enum Bar {
    D, E, F
  }

A continuación, puede aplicar el tipo de mapa que está hablando con el siguiente código.

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();
    }
  }

Esto no moverse por un elenco sin control, sin embargo; sólo lo oculta a usted temporalmente. Se puede ver en donde SuppressWarningsse utiliza para amortiguar la advertencia sobre enumType. Por lo general es una buena práctica aplicar la supresión de advertencia en tan limitado alcance posible. En este caso, es para que la sola asignación. Si bien esto podría ser una señal de alerta, en general, en el presente caso sabemos que los únicos valores en el mapa son, de hecho, las clases de enumeración, ya que deben haber sido añadida por addEnum.

A continuación, se puede utilizar como:

  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")));

que imprime:

A
E
[B, D, C]

Se dará cuenta de que he roto parseUnsafelyy parseen métodos separados. La razón de que no queremos exponer parseUnsafelydirectamente es que hace una garantía por su tipo de retorno que en realidad no podemos cumplir. Si se expone, entonces podríamos escribir código como

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

que compila, pero falla en tiempo de ejecución con una excepción clase fundido.

Supongo que te gusta

Origin http://43.154.161.224:23101/article/api/json?id=187112&siteId=1
Recomendado
Clasificación