Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Iterate enum values using java generics

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 what I want to do. Note that the code T.values() is not valid in the following code.

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

Here is how I would instantiate a Filter object:

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

The enum is defined as follows:

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

I realize it might not make sense to copy a enum's values to a list, but I'm using a library that needs a list of values as input and won't work with enums.


EDIT 2/5/2010:

Most of the answers proposed are very similar and suggest doing something like this:

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

This would work great if I can be sure that selectedOption has a non-null value. Unfortunately, in my use case, this value is often null, as there is a public Filter() no-arg constructor as well. This means I can't do a selectedOption.getClass() without getting an NPE. This filter class manages a list of available options which of the options is selected. When nothing is selected, selectedOption is null.

The only thing I can think to solve this is to actually pass in a Class in the constructor. So something like this:

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

Any ideas how to do this without needing an extra Class parameter in the constructors?

like image 576
Tauren Avatar asked Feb 05 '10 08:02

Tauren


People also ask

Can we iterate enum in Java?

Enumeration (enum) in Java is a datatype which stores a set of constant values. You can use enumerations to store fixed values such as days in a week, months in a year etc. You can iterate the contents of an enumeration using for loop, using forEach loop and, using java.

How iterate through all enum values?

Enums don't have methods for iteration, like forEach() or iterator(). Instead, we can use the array of the Enum values returned by the values() method.

Can we loop through enum?

Yes. Use GetValues() method in System. Enum class.

Can enum be generic?

Enum, Interfaces, and Generics Enum cannot extend a class, but can implement an interface because Java does not support multiple inheritances of classes but multiple implementation of interfaces. The enum is a default subclass of the generic Enum<T> class, where T represents generic enum type.


2 Answers

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());         } } 
like image 189
Thirler Avatar answered Sep 21 '22 17:09

Thirler


Another option is to use 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);     }   } 
like image 45
Miserable Variable Avatar answered Sep 19 '22 17:09

Miserable Variable