Enum type param in Java

I ran into an interesting Java generics issue when writing my solution to HW1 for CSE 546 this past weekend. I wanted to make a generic ID3Tree class so that I could test my decision tree with different inputs (i.e. the examples in the book) easily. I wanted to make the tree’s classification type the generic type parameter for the class, and since I was only dealing with discrete types, I wanted to make a class that accepted any enum as a type parameter. All Java enums are classes that extend Enum, so I initially just wrote a header like this:

public class ID3Tree<E extends Enum<E>> { ...

I then attempted to use E.values() and E.valueOf(), but got compiler errors. Apparently, these methods are not inherited from Enum (they don’t exist in Enum at all) but they are added by the compiler when the compiler translates the enum into a public final class.

My initial thought was, no problem, I’ll just add a wrapper interface that I’ll make the enums implement that have values() and valueOf(). Except wait, you can’t put static methods in an interface. And I can’t make the enums extend a class with the necessary methods because a) single inheritance (they already extend Enum) and b) even if I could extend a second class, static methods are hidden, not overridden when defined in subclasses.

So my workaround was to still make a wrapper interface Classifier<E extends Enum<E>> with instance methods for values() and valueOf(), then make the ID3Tree constructor take a Classifier object parameter.

Code skeleton below… kind of gross. But thought I’d post in case someone else ran into a similar problem. If there is some cleaner workaround, let me know! Kevin suggested Reflection, which I always forget about. Other ideas?

public class ID3Tree<E extends Enum<E>> {
    private Classifier<E> classifier;
    public ID3Tree(Classifier<E> c, ...)
        classifier = c;
        ...
    }
}

public interface Classifier<E extends Enum<E>> {
    public E[] values();
    public E valueOf(String name);
}

EDIT: Kevin for the save! Check out this awesome alternative solution:

public class Foo<E extends Enum> {
    private E[] values;
    public Foo(Class cls) {
        this.values = cls.getEnumConstants();
    }
}

I love the description for getEnumConstants(). This method was sooo clearly added as an afterthought, lol :thumbup:

2 Comments »

January 22, 2010 2:50 pm

After some experimentation:

public class Foo<E extends Enum> {
    private E[] values;

    public Foo(Class cls) {
        this.values = cls.getEnumConstants();
    }

    public void printValues() {
        for(E value : values) {
            System.out.println(value);
        }
    }

    public static void main(String[] args) {
        new Foo(Bar.class).printValues();
    }
}

enum Bar {
    ONE, TWO, THREE, FOUR
}


January 23, 2010 3:03 am

getEnumConstants():

Returns: an array containing the values comprising the enum class represented by this Class object in the order they’re declared, or null if this Class object does not represent an enum type

LOL I LOVE IT


RSS feed for comments on this post. TrackBack URL

Leave a comment

;-) :thumbup: :thumbdown: :sweat: :sun: :snow: :shing2: :shing1: :sad: :pencil: :partcloud: :note: :minisweat2: :minisweat1: :mininote: :minimad2: :minimad1: :miniheart: :minidread: :lightening: :heart: :happy: :girlsad: :girlpout: :girlnormal: :girlmad: :girlhappy: :girleh: :girlconf: :girlblank: :food: :flower: :coffee: :cloud: :...: :-| :-P :-D :-) :-(