with values usar recorrer que enum como clase java generics enums enumeration

values - Iterar los valores enum usando java generics



que es un enum en java (9)

Aquí debajo un ejemplo de una clase de contenedor alrededor de un Enum. Es un poco raro lo que necesito:

public class W2UIEnum<T extends Enum<T> & Resumable> { public String id; public String caption; public W2UIEnum(ApplicationContext appContext, T t) { this.id = t.getResume(); this.caption = I18N.singleInstance.getI18nString(t.name(), "enum_" + t.getClass().getSimpleName().substring(0, 1).toLowerCase() + t.getClass().getSimpleName().substring(1, t.getClass().getSimpleName().length()), appContext .getLocale()); } public static <T extends Enum<T> & Resumable> List<W2UIEnum<T>> values( ApplicationContext appContext, Class<T> enumType) { List<W2UIEnum<T>> statusList = new ArrayList<W2UIEnum<T>>(); for (T status : enumType.getEnumConstants()) { statusList.add(new W2UIEnum(appContext, status)); } return statusList; }

}

Estoy tratando de encontrar una forma de iterar a través de los valores de una enumeración mientras uso genéricos. No estoy seguro de cómo hacer esto o si es posible.

El siguiente código ilustra lo que quiero hacer. Tenga en cuenta que el código T.values ​​() no es válido en el siguiente código.

public class Filter<T> { private List<T> availableOptions = new ArrayList<T>(); private T selectedOption; public Filter(T selectedOption) { this.selectedOption = selectedOption; for (T option : T.values()) { // INVALID CODE availableOptions.add(option); } } }

Así es como crearía una instancia de un objeto Filtro:

Filter<TimePeriod> filter = new Filter<TimePeriod>(TimePeriod.ALL);

La enumeración se define de la siguiente manera:

public enum TimePeriod { ALL("All"), FUTURE("Future"), NEXT7DAYS("Next 7 Days"), NEXT14DAYS("Next 14 Days"), NEXT30DAYS("Next 30 Days"), PAST("Past"), LAST7DAYS("Last 7 Days"), LAST14DAYS("Last 14 Days"), LAST30DAYS("Last 30 Days"); private final String name; private TimePeriod(String name) { this.name = name; } @Override public String toString() { return name; } }

Me doy cuenta de que no tiene sentido copiar los valores de una enumeración en una lista, pero estoy usando una biblioteca que necesita una lista de valores como entrada y no funcionará con las enumeraciones.

EDITAR 2/5/2010:

La mayoría de las respuestas propuestas son muy similares y sugieren hacer algo como esto:

class Filter<T extends Enum<T>> { private List<T> availableOptions = new ArrayList<T>(); private T selectedOption; public Filter(T selectedOption) { Class<T> clazz = (Class<T>) selectedOption.getClass(); for (T option : clazz.getEnumConstants()) { availableOptions.add(option); } } }

Esto funcionaría muy bien si puedo estar seguro de que selectedOption tiene un valor no nulo. Desafortunadamente, en mi caso de uso, este valor suele ser nulo, ya que también hay un constructor público de filtro () no-arg. Esto significa que no puedo hacer una selectedOption.getClass () sin obtener un NPE. Esta clase de filtro administra una lista de opciones disponibles que de las opciones se selecciona. Cuando no se selecciona nada, selectedOption es nulo.

Lo único que puedo pensar para resolver esto es pasar una Class en el constructor. Entonces algo como esto:

class Filter<T extends Enum<T>> { private List<T> availableOptions = new ArrayList<T>(); private T selectedOption; public Filter(Class<T> clazz) { this(clazz,null); } public Filter(Class<T> clazz, T selectedOption) { this.selectedOption = selectedOption; for (T option : clazz.getEnumConstants()) { availableOptions.add(option); } } }

¿Alguna idea de cómo hacer esto sin necesitar un parámetro de clase adicional en los constructores?


El problema de raíz es que necesitas convertir una matriz a una lista, ¿verdad? Puede hacerlo, utilizando un tipo específico (TimePeriod en lugar de T) y el siguiente código.

Entonces usa algo como esto:

List<TimePeriod> list = new ArrayList<TimePeriod>(); list.addAll(Arrays.asList(sizes));

Ahora puede pasar la lista a cualquier método que quiera una lista.


Este es un problema difícil de hecho. Una de las cosas que debes hacer es decirle a Java que estás usando una enumeración. Esto es al afirmar que extiendes la clase Enum para tus genéricos. Sin embargo, esta clase no tiene la función de valores (). Entonces debes tomar la clase para la cual puedes obtener los valores.

El siguiente ejemplo debería ayudarlo a solucionar su problema:

public <T extends Enum<T>> void enumValues(Class<T> enumType) { for (T c : enumType.getEnumConstants()) { System.out.println(c.name()); } }


Otra opción es usar EnumSet:

class PrintEnumConsants { static <E extends Enum <E>> void foo(Class<E> elemType) { for (E e : java.util.EnumSet.allOf(elemType)) { System.out.println(e); } } enum Color{RED,YELLOW,BLUE}; public static void main(String[] args) { foo(Color.class); } }


Para completar, JDK8 nos brinda una forma relativamente más limpia y concisa de lograr esto sin la necesidad de usar los values() sintéticos values() en la clase Enum:

Dado una enumeración simple:

private enum TestEnum { A, B, C }

Y un cliente de prueba:

@Test public void testAllValues() { System.out.println(collectAllEnumValues(TestEnum.class)); }

Esto imprimirá {A, B, C} :

public static <T extends Enum<T>> String collectAllEnumValues(Class<T> clazz) { return EnumSet.allOf(clazz).stream() .map(Enum::name) .collect(Collectors.joining(", " , "/"{", "}/"")); }

El código puede ser trivialmente adaptado para recuperar diferentes elementos o para recopilar de una manera diferente.


Para obtener el valor de la enumeración genérica:

protected Set<String> enum2set(Class<? extends Enum<?>> e) { Enum<?>[] enums = e.getEnumConstants(); String[] names = new String[enums.length]; for (int i = 0; i < enums.length; i++) { names[i] = enums[i].toString(); } return new HashSet<String>(Arrays.asList(names)); }

Tenga en cuenta en el método anterior la llamada al método toString ().

Y luego defina la enumeración con dicho método toString ().

public enum MyNameEnum { MR("John"), MRS("Anna"); private String name; private MyNameEnum(String name) { this.name = name; } public String toString() { return this.name; } }


Si declara Filtro como

public class Filter<T extends Iterable>

entonces

import java.util.Iterator; public enum TimePeriod implements Iterable { ALL("All"), FUTURE("Future"), NEXT7DAYS("Next 7 Days"), NEXT14DAYS("Next 14 Days"), NEXT30DAYS("Next 30 Days"), PAST("Past"), LAST7DAYS("Last 7 Days"), LAST14DAYS("Last 14 Days"), LAST30DAYS("Last 30 Days"); private final String name; private TimePeriod(String name) { this.name = name; } @Override public String toString() { return name; } public Iterator<TimePeriod> iterator() { return new Iterator<TimePeriod>() { private int index; @Override public boolean hasNext() { return index < LAST30DAYS.ordinal(); } @Override public TimePeriod next() { switch(index++) { case 0 : return ALL; case 1 : return FUTURE; case 2 : return NEXT7DAYS; case 3 : return NEXT14DAYS; case 4 : return NEXT30DAYS; case 5 : return PAST; case 6 : return LAST7DAYS; case 7 : return LAST14DAYS; case 8 : return LAST30DAYS; default: throw new IllegalStateException(); } } @Override public void remove() { throw new UnsupportedOperationException(); } }; } }

Y el uso es bastante fácil:

public class Filter<T> { private List<T> availableOptions = new ArrayList<T>(); private T selectedOption; public Filter(T selectedOption) { this.selectedOption = selectedOption; Iterator<TimePeriod> it = selectedOption.iterator(); while(it.hasNext()) { availableOptions.add(it.next()); } } }


Si está seguro de que selectedOption del Filter(T selectedOption) constructor Filter(T selectedOption) no es nulo. Puedes usar la reflexión Me gusta esto.

public class Filter<T> { private List<T> availableOptions = new ArrayList<T>(); private T selectedOption; public Filter(T selectedOption) { this.selectedOption = selectedOption; for (T option : this.selectedOption.getClass().getEnumConstants()) { // INVALID CODE availableOptions.add(option); } } }

Espero que esto ayude.


Usando un lanzamiento inseguro:

class Filter<T extends Enum<T>> { private List<T> availableOptions = new ArrayList<T>(); private T selectedOption; public Filter(T selectedOption) { Class<T> clazz = (Class<T>) selectedOption.getClass(); for (T option : clazz.getEnumConstants()) { availableOptions.add(option); } } }