如何要求泛型参数是实现接口的枚举?

Posted

技术标签:

【中文标题】如何要求泛型参数是实现接口的枚举?【英文标题】:How can I require a generic parameter to be an enum that implements an interface? 【发布时间】:2009-07-01 18:44:09 【问题描述】:

我不是 100% 相信这是一个好主意,但我今天遇到了一些代码,目前实现如下:

class MyWidget <T extends Enum<T> > 
  MyWidget(Map<T, Integer> valueMap) 
    mValueMap = valueMap;
  

  Map<T, Integer> mValueMap;

其中MyWidget 然后提供使用mValueMap 将传入的Enum 转换为Integer 或从Integer 转换的方法。

我正在考虑做的是尝试重构它,以便我声明我的枚举:

interface MyInterface 
  public Integer getValue();


enum MyEnum implements MyInterface 
  foo, bar;
  public Integer getValue() 
    return ordinal();
  

然后我就可以将MyWidget 重写为看起来像这样的东西:

public class MyWidget<T extends Enum<T> extends MyInterface> 
  ...

然后就可以在MyWidget 内的T 类型对象上从MyInterface 调用getValue() 方法。当然,问题在于“&lt;T extends Enum&lt;T&gt; extends MyInterface&gt;”不是有效的语法。有没有办法解决这个问题?

我不想只有MyWidget&lt;T extends MyInterface&gt;,因为 T 是一个枚举也很重要。

提前致谢!

【问题讨论】:

【参考方案1】:

改用“&amp;”:

public class MyWidget<T extends Enum<T> & MyInterface> 
    ...

JLS 将此称为“交集类型”,但我在 Java 教程中找不到任何提及。我只想说它完全符合您希望 "extends" 会做的事情。

另外,我应该提到,您可以在交集类型中拥有任意数量的类型。所以如果你愿意,你可以这样做:

public class MyWidget<T extends Enum<T> & MyInterface & Serializable & Cloneable> 
    ...

[注意:此代码示例不应被视为对Cloneable 接口的认可;它当时只是很方便。]

【讨论】:

& 语法很简洁,但我发现使用它通常会产生代码异味,这表明你的模型有些地方不太对劲。 我倾向于同意(我想我可能用过一次或两次,如果那样的话)。但在枚举实现接口的情况下,我认为是合适的。 谢谢。你的帖子不知何故让我意识到,我真正需要的是……doSomething(Enum&lt;? extends SomeInterface&gt;) @skaffmann 如果你有时间分享你的 WRT 相关经验代码味道,我真的很感激 +10 我自己永远也想不通。使用接口处理枚举的唯一方法。【参考方案2】:

JDK 7 的 JSR 203(新的新 IO)东西大量使用实现接口的枚举(例如:http://openjdk.java.net/projects/nio/javadoc/java/nio/file/FileVisitOption.html),以便它们在未来有一些回旋余地,以便将来使用更多的枚举选项集.所以这是一种可行的方法,显然是在一个大型 Sun 项目中经过深思熟虑后选择的。

【讨论】:

整洁。希望 java 7 能在我的胡子变灰之前出现。 从编写少量代码使用这些东西,我的印象是它有点奇怪。不能说我在别的地方见过。我敢肯定,名称中带有 7 的东西将在 2010 年发布。我不知道它是否会是 JCP 认可的“Java 7”。现在只有甲骨文可以回答这个问题...... docs.oracle.com/javase/8/docs/api/java/nio/file/…

以上是关于如何要求泛型参数是实现接口的枚举?的主要内容,如果未能解决你的问题,请参考以下文章

Kotlin 五 泛型 枚举

泛型反射和异常

将接口上的泛型参数限制为子类

泛型类型参数是实现接口的类

当两个类型参数在C#中实现公共接口时,如何将泛型强制转换为它实现的接口

检查类型是不是实现了泛型接口而不考虑泛型类型参数