Enum constants implementing generic interfaces in Java

enums, generics, interface, java

Solution

No, as amalloy pointed out, Java doesn't allow enums to be declared with type parameters. It becomes clear why if you think about the way enums are meant to be used, for example in a `switch`.

Also consider how the language would implement generic enums - it isn't trivial. For a generic enum `MyEnum<T>`, each enum constant would need to resolve `T` to some specific type, otherwise they wouldn't be constants at all. Consider this:

enum MyEnum<T> {
    FOO; // T is not resolved
}

What is `T` for `FOO` here? The language would need a new syntax just to be able to express it, for example:

enum MyEnum<T> {
    FOO<String>;
}

So now we're getting into added complexity for the language in order to support semantics that don't have an overly compelling use case. It's easy to see why the language designers would have simply nixed type parameters for enums.

The workaround:

You can emulate your desired pattern by simply not using an enum. Organize the implementations of your interface into a utility class:

public class MyImplementations {

    public static final MyInterface<Integer> FOO =
            new MyInterface<Integer>() {
                ...
            };

    public static final MyInterface<String> BAR =
            new MyInterface<String>() {
                ...
            };

    public static final MyInterface<List<MyOtherType>> BAZ =
            new MyInterface<List<MyOtherType>>() {
                ...
            };

    private MyImplementations() { }
}

The only thing inherently missing is a way to iterate over the different implementations, as you could have done with `MyEnum.values()` - but with a hypothetical `MyEnum<T>`, the most specific type you could iterate over would be `MyEnum<?>`.

Problem

Suppose you have a generic interface: ``` public interface MyInterface<T> { T doSomething(); } ``` Is it possible to declare an enum that implements `MyInterface<T>`, but for which which every enum constant implements it for a different value of `T`? That is, given this enum: ``` public enum MyEnum { FOO, BAR, BAZ; } ``` can we change it so that `FOO` implements `MyInterface<Integer>`, `BAR` implements `MyInterface<String>`, and `BAZ` implements `MyInterface<List<MyOtherType>>`, and make it so that `MyEnum` overall implements `MyInterface<?>`? It seems entirely feasible doing this raw, so it may be the case that it can be done in a typesafe manner.

Original source