使用Javagenerics迭代枚举值

我试图find一种方法来遍历枚举的值,而使用generics。 不知道如何做到这一点,如果可能的话。

下面的代码演示了我想要做什么。 请注意代码T.values()在下面的代码中无效。

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

下面是我将如何实例化一个Filter对象:

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

枚举定义如下:

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

我意识到将枚举的值复制到列表中可能没有意义,但是我使用的库需要一个值列表作为input,并且不能使用枚举。


编辑2/5/2010:

大部分提出的答案都非常相似,并build议做这样的事情:

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

如果我能确定selectedOption有一个非空值,这将工作得很好。 不幸的是,在我的用例中,这个值通常是空的,因为还有一个公共的Filter() no-arg构造函数。 这意味着我不能做一个selectedOption.getClass()没有得到一个NPE。 此筛选器类pipe理可用选项的列表,select哪个选项。 当没有select时,selectedOption为null。

我唯一能想到的解决办法就是在构造函数中传入一个类。 所以像这样的东西:

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

任何想法如何做到这一点,而不需要在构造函数中额外的类参数?

这确实是一个难题。 你需要做的事情之一是告诉java你正在使用枚举。 这是说,你扩展了generics类的generics。 但是这个类没有values()函数。 所以你必须拿到你能获得价值的课程。

下面的例子可以帮助你解决你的问题:

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

另一种select是使用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); } } 

使用不安全的演员:

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

为了完整起见,JDK8给了我们一个相对简洁而又简洁的方法来实现这一点,而不需要在Enum类中使用合成values()

给定一个简单的枚举:

 private enum TestEnum { A, B, C } 

和一个testing客户端:

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

这将打印{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(", " , "\"{", "}\"")); } 

代码可以简单地适用于检索不同的元素或以不同的方式收集。

如果您确定构造函数Filter(T selectedOption)不为null。 你可以使用reflection。 喜欢这个。

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

希望这可以帮助。

根本问题是你需要将数组转换为列表,对吧? 您可以通过使用特定types(TimePeriod而不是T)和下面的代码来完成此操作。

所以使用这样的东西:

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

现在,您可以将列表传递给想要列表的任何方法。

如果你声明过滤为

 public class Filter<T extends Iterable> 

然后

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

用法很简单:

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

下面是一个Enum包装类的例子。 有点怪我是需要的:

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

}

为了得到generics枚举的

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

在上面的方法中请注意toString()方法的调用。

然后用这样的toString()方法定义枚举。

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