使用java泛型迭代枚举值

使用java泛型迭代枚举值,java,generics,enums,enumeration,Java,Generics,Enums,Enumeration,我试图找到一种在使用泛型时遍历枚举值的方法。不知道该如何做,或者是否可能 下面的代码说明了我想做什么。请注意,代码T.values()在以下代码中无效 public class Filter<T> { private List<T> availableOptions = new ArrayList<T>(); private T selectedOption; public Filter(T selectedOption) {

我试图找到一种在使用泛型时遍历枚举值的方法。不知道该如何做,或者是否可能

下面的代码说明了我想做什么。请注意,代码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);
        }
    }
}
我意识到将枚举的值复制到列表可能没有意义,但我使用的库需要一个值列表作为输入,不能使用枚举


2010年2月5日编辑:

大多数建议的答案非常相似,建议采取以下措施:

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);
        }
    }
}
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);
        }
    }
}
List<TimePeriod> list = new ArrayList<TimePeriod>();
list.addAll(Arrays.asList(sizes));
类过滤器{
private List availableOptions=new ArrayList();
私人T选择选项;
公共过滤器(T选择选项){
Class clazz=(Class)selectedOption.getClass();
对于(T选项:clazz.getEnumConstants()){
可用选项。添加(选项);
}
}
}
如果我能确保selectedOption具有非空值,这将非常有用。不幸的是,在我的用例中,这个值通常为null,因为有一个公共过滤器()也没有参数构造函数。这意味着如果没有NPE,我无法执行selectedOption.getClass()。此筛选器类管理可用选项的列表,其中选择了哪些选项。未选择任何内容时,selectedOption为空

我唯一能想到的解决方法就是在构造函数中实际传入一个类。比如说:

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);
        }
    }
}
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);
        }
    }
}
List<TimePeriod> list = new ArrayList<TimePeriod>();
list.addAll(Arrays.asList(sizes));
类过滤器{
private List availableOptions=new ArrayList();
私人T选择选项;
公共过滤器(clazz类){
这个(clazz,null);
}
公共筛选器(类clazz,T selected选项){
this.selectedOption=selectedOption;
对于(T选项:clazz.getEnumConstants()){
可用选项。添加(选项);
}
}
}

你知道如何在不需要构造函数中额外的类参数的情况下实现这一点吗?

这确实是一个难题。您需要做的一件事是告诉java您正在使用枚举。这是通过声明为泛型扩展Enum类来实现的。但是,此类没有values()函数。因此,您必须选择可以获取其值的类

以下示例将帮助您解决问题:

public <T extends Enum<T>> void enumValues(Class<T> enumType) {
        for (T c : enumType.getEnumConstants()) {
             System.out.println(c.name());
        }
}
public void枚举值(类枚举类型){
对于(tc:enumType.getEnumConstants()){
System.out.println(c.name());
}
}

根本问题是需要将数组转换为列表,对吗?您可以通过使用特定类型(TimePeriod而不是T)和以下代码来实现这一点

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);
        }
    }
}
因此,请使用类似这样的方法:

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);
        }
    }
}
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);
        }
    }
}
List<TimePeriod> list = new ArrayList<TimePeriod>();
list.addAll(Arrays.asList(sizes));
List List=new ArrayList();
addAll(Arrays.asList(size));

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

如果您确定构造函数
过滤器(T selectedOption)
selectedOption
不为空。你可以使用反射。像这样

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);
        }
    }
}
公共类过滤器{
private List availableOptions=new ArrayList();
私人T选择选项;
公共过滤器(T选择选项){
this.selectedOption=selectedOption;
对于(T选项:this.selectedOption.getClass().getEnumConstants()){//无效代码
可用选项。添加(选项);
}
}
}
希望这有帮助。

使用不安全的石膏:

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);
        }
    }
}
类过滤器{
private List availableOptions=new ArrayList();
私人T选择选项;
公共过滤器(T选择选项){
Class clazz=(Class)selectedOption.getClass();
对于(T选项:clazz.getEnumConstants()){
可用选项。添加(选项);
}
}
}

另一个选项是使用枚举集:

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

}
类printEnumConstants{
静态void foo(类elemType){
for(E:java.util.EnumSet.allOf(elemType)){
系统输出打印ln(e);
}
}
枚举颜色{红、黄、蓝};
公共静态void main(字符串[]args){
foo(Color.class);
} 
}

如果将过滤器声明为

public class Filter<T extends Iterable>
公共类过滤器
然后

import java.util.Iterator;
公共枚举时间段实现了Iterable{
全部(“全部”),
未来(“未来”),
下一个7天(“下一个7天”),
未来14天(“未来14天”),
未来30天(“未来30天”),
过去(“过去”),
最后7天(“最后7天”),
最后14天(“最后14天”),
最后30天(“最后30天”);
私有最终字符串名;
专用时间段(字符串名称){
this.name=名称;
}
@凌驾
公共字符串toString(){
返回名称;
}
公共迭代器迭代器(){
返回新的迭代器(){
私有整数索引;
@凌驾
公共布尔hasNext(){
返回指数
而且使用非常简单:

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());
        }
    }
}
公共类过滤器{
private List availableOptions=new ArrayList();
私人T选择选项;
公共过滤器(T选择选项){
this.selectedOption=selectedOption;
Iterator it=selectedOption.Iterator();
  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));
  }
public enum MyNameEnum {

  MR("John"), MRS("Anna");

  private String name;

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

  public String toString() {
    return this.name;
  }

}
    protected List<String> enumToList(Class<? extends Enum<?>> e) {
            Enum<?>[] enums = e.getEnumConstants();
            return Arrays.asList(enums).stream()
                   .map(name -> name.toString())
                   .collect(Collectors.toList());
        }