Java中实现通用接口的枚举常量

10
假设您有一个通用接口:
```

假设您有一个通用接口:

```
public interface MyInterface<T> {
    T doSomething();
}

是否可以声明一个实现了MyInterface<T>的枚举,但是每个枚举常量都为T的不同值实现它?也就是说,给定这个枚举:

public enum MyEnum {
    FOO,
    BAR,
    BAZ;
}

我们能否改变代码,让FOO实现MyInterface<Integer>BAR实现MyInterface<String>BAZ实现MyInterface<List<MyOtherType>>,并且使得MyEnum整体实现MyInterface<?>?这看起来完全可行,因此有可能以类型安全的方式完成。请注意保留HTML标签。
2个回答

12
不,正如amalloy指出的,Java不允许使用类型参数声明枚举。如果您考虑枚举的用法,例如在switch中,就会明白为什么了。
还要考虑语言如何实现通用枚举-这并不是微不足道的。对于通用枚举MyEnum<T>,每个枚举常量都需要将T解析为某个特定类型,否则它们根本不是常量。考虑以下情况:
enum MyEnum<T> {
    FOO; // T is not resolved
}

这里的T是什么意思?为了表达它,语言需要一个新的语法,例如:

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

现在,我们需要增加语言的复杂性以支持没有过于强烈的用例的语义。很容易理解为什么语言设计者会简单地取消枚举类型参数。

解决方法:

您可以通过不使用枚举来模拟所需的模式。将接口的实现组织到一个实用程序类中:

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

唯一的缺失之处就是一种可以迭代不同实现的方法,就像你可以使用MyEnum.values()一样 - 但是对于一个假设的MyEnum<T>,你可以迭代的最具体类型将会是MyEnum<?>

这可能是最好的答案,其中包括替代方案和解释为什么不可能。 - Tomo

4

不行。有人怎么可能使用这样的类呢?

MyEnum x = whatever;
x.foo().get(0); // how can javac know that x is the version that gives back a List?

1
使用我上面的例子,我本来以为javac会知道像MyEnum.FOO.doSomething()这样显式的调用会返回Integer,而像你上面的表达式(比如,如果x是传递给方法的参数)则会在编译时出错,因为MyEnum本身将实现MyInterface <?>,而get()不是Object中的方法。总的来说,这似乎与枚举常量的类型是其自身的最终单例子类的概念相矛盾。 - Kelvin Chung

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接