Konstantin Milyutin
Konstantin Milyutin

Reputation: 12366

Is it possible to create generic enum?

I'm trying to define generic enum, but have problems with it:

private enum Stick<T>{
    A, B, C;

    private Stack<T> disks = new Stack();

    public void print(){
        System.out.println(this.name() + ": " + disks);
    }

    public T pop(){
        return disks.pop();
    }

    public void push(T element){
        disks.push(element);
    }

};

Is it possible at all?

Upvotes: 2

Views: 4567

Answers (4)

Leejjon
Leejjon

Reputation: 756

There is a draft for generic enums here: http://openjdk.java.net/jeps/301

Hope it makes it into Java 10!

Upvotes: 0

Bozho
Bozho

Reputation: 597106

Enums are constants. So Stack disks can not be "stack of whatever type the client of the enum wants". It has to be of fixed type.

The point of having fields in an enum is to be able to hold additional information about each element. For example, in the case of a stack, this could be A("a", "b"), B("b", "c", "d") - each element specify what items are loaded in its stack (the example requires a varargs constructor). But their type is strictly specified, it cannot be <T>.

The error that the eclipse compiler shows is clear:

Syntax error, enum declaration cannot have type parameters

However, you can do something like that:

enum Foo {
    A("foo", "bar"),
    B(0, 1, 2);
    private Stack<?> stack;
    private <T> Foo(T... args) {
        stack = new Stack<T>();
        stack.addAll(Arrays.asList(args));
    }
    public <T> Stack<T> getStack() {
        return (Stack<T>) stack;
    }
}

And then:

Stack<String> stack1 = Foo.A.getStack();
Stack<Integer> stack2 = Foo.B.getStack();

System.out.println(stack1);
System.out.println(stack2);

Results in:

[foo, bar]
[0, 1, 2]

Update: Since your comment about your goal - the hanoi towers should not be enums, because their values are changing. Instead, you should use the enums as keys to a Map, where the values are the stacks. I admit that it looks tempting to use a field of the enum to do that, but it is not a good practice. Enums better be constant. Of course, you can use my example above to achieve your initial goal, but I'd recommend a Map.

Upvotes: 12

Lucas
Lucas

Reputation: 14949

This could help. Basically, you need this:

public interface Stick<E extends Enum<E>>

Upvotes: 0

DerMike
DerMike

Reputation: 16190

No, but Enums can implement interfaces. May be that helps you.

Upvotes: 0

Related Questions