Iterate enum values using java generics

前端 未结 10 952
余生分开走
余生分开走 2020-12-02 10:55

I\'m trying to find a way to iterate through an enum\'s values while using generics. Not sure how to do this or if it is possible.

The following code illustrates

相关标签:
10条回答
  • 2020-12-02 11:22

    If you are sure that selectedOption of the constructor Filter(T selectedOption) is not null. You can use reflection. Like this.

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

    Hope this helps.

    0 讨论(0)
  • 2020-12-02 11:23

    For completeness, JDK8 gives us a relatively clean and more concise way of achieving this without the need to use the synthethic values() in Enum class:

    Given a simple enum:

    private enum TestEnum {
        A,
        B,
        C
    }
    

    And a test client:

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

    This will print {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(", " , "\"{", "}\""));
    }
    

    Code can be trivially adapted to retrieve different elements or to collect in a different way.

    0 讨论(0)
  • 2020-12-02 11:24

    If you declare Filter as

    public class Filter<T extends Iterable>
    

    then

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

    And usage is quite easy:

    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());
            }
        }
    }
    
    0 讨论(0)
  • 2020-12-02 11:31

    The root problem is that you need to convert an array to a list, right? You can do this, by using a specific type (TimePeriod instead of T), and the following code.

    So use something like this:

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

    Now you can pass list into any method that wants a list.

    0 讨论(0)
  • 2020-12-02 11:34

    This is a hard problem indeed. One of the things you need to do is tell java that you are using an enum. This is by stating that you extend the Enum class for your generics. However this class doesn't have the values() function. So you have to take the class for which you can get the values.

    The following example should help you fix your problem:

    public <T extends Enum<T>> void enumValues(Class<T> enumType) {
            for (T c : enumType.getEnumConstants()) {
                 System.out.println(c.name());
            }
    }
    
    0 讨论(0)
  • 2020-12-02 11:34

    Using an unsafe cast:

    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);
            }
        }
    }
    
    0 讨论(0)
提交回复
热议问题