首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >在枚举中使用Java泛型

在枚举中使用Java泛型
EN

Stack Overflow用户
提问于 2009-07-23 17:31:03
回答 4查看 49.7K关注 0票数 18

更新:感谢大家的帮助-这个问题的答案在于我在更复杂的代码中没有注意到的东西,以及我不知道的Java5协变返回类型。

原文:

今天早上我一直在摆弄一些东西。虽然我知道我可以用不同的方式解决整个问题,但我发现自己一直在纠结于找出为什么它不像我预期的那样工作。在花了一些时间阅读这篇文章后,我发现我还没有更深入地理解它,所以我把它作为一个问题提出来,看看我是不是太愚蠢了,或者是否真的有什么我不明白的地方。

我创建了一个自定义事件层次结构,如下所示:

代码语言:javascript
复制
public abstract class AbstractEvent<S, T extends Enum<T>>
{
    private S src;
    private T id;

    public AbstractEvent(S src, T id)
    {
        this.src = src;
        this.id = id;
    }

    public S getSource()
    {
        return src;
    }

    public T getId()
    {
        return id;
    }
}

使用如下的具体实现:

代码语言:javascript
复制
public class MyEvent
extends AbstractEvent<String, MyEvent.Type>
{
    public enum Type { SELECTED, SELECTION_CLEARED };

    public MyEvent(String src, Type t)
    {
        super(src, t);
    }
}

然后我创建一个事件,如下所示:

代码语言:javascript
复制
fireEvent(new MyEvent("MyClass.myMethod", MyEvent.Type.SELECTED));

其中,我的fireEvent定义为:

代码语言:javascript
复制
protected void fireEvent(MyEvent event)
{
    for(EventListener l : getListeners())
    {
        switch(event.getId())
        {
            case SELECTED:
                l.selected(event);
                break;
            case SELECTION_CLEARED:
                l.unselect(event);
                break;
         }
    }
}

所以我认为这会非常简单,但结果是调用event.getId()会导致编译器告诉我不能打开枚举,只能打开可转换的int值或枚举常量。

可以将以下方法添加到MyEvent:

代码语言:javascript
复制
public Type getId()
{
    return super.getId();
}

一旦我这样做了,一切就完全按照我的预期工作了。我不仅仅对找到解决这个问题的方法感兴趣(因为我显然有一个),我感兴趣的是人们可能有的任何洞察力,为什么它不能像我期望的那样立即工作。

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2009-07-23 17:52:31

Yishai是对的,神奇的短语是"covariant return types“,这是Java5.0的新特性--您不能打开Enum,但是可以打开扩展Enum的Type类。MyEvent继承的AbstractEvent中的方法会受到类型擦除的影响。通过覆盖它,您可以将getId()的结果重定向到您的Type类,使其在运行时可以处理。

票数 11
EN

Stack Overflow用户

发布于 2009-07-23 17:34:52

这与泛型无关。java中枚举的Switch语句只能使用特定枚举的值,因此禁止实际指定枚举名称。这应该是可行的:

代码语言:javascript
复制
switch(event.getId()) {
   case SELECTED:
         l.selected(event);
         break;
   case SELECTION_CLEARED:
         l.unselect(event);
         break;
}

更新:好的,这是我复制/粘贴、编译和运行的实际代码(我不得不稍微修改它,使其不依赖于任何依赖项)--没有错误:

AbstractEvent.java

代码语言:javascript
复制
public abstract class AbstractEvent<S, T extends Enum<T>> {
    private S src;
    private T id;

    public AbstractEvent(S src, T id) {
        this.src = src;
        this.id = id;
    }

    public S getSource() {
        return src;
    }

    public T getId() {
        return id;
    }
}

MyEvent.java

代码语言:javascript
复制
public class MyEvent extends AbstractEvent<String, MyEvent.Type> {
    public enum Type { SELECTED, SELECTION_CLEARED };

    public MyEvent(String src, Type t) {
        super(src, t);
    }
}

Test.java

代码语言:javascript
复制
public class Test {
  public static void main(String[] args) {
      fireEvent(new MyEvent("MyClass.myMethod", MyEvent.Type.SELECTED));
  }

  private static void fireEvent(MyEvent event) {
        switch(event.getId()) {
            case SELECTED:
                System.out.println("SELECTED");
                break;
            case SELECTION_CLEARED:
                System.out.println("UNSELECTED");
                break;
         }
    }
}

它可以在Java1.5下编译和运行。这里我漏掉了什么?

票数 8
EN

Stack Overflow用户

发布于 2009-07-23 18:08:57

这对我很有效。

完整的剪切粘贴测试程序:

代码语言:javascript
复制
enum MyEnum {
    A, B
}
class Abstract<E extends Enum<E>> {
    private final E e;
    public Abstract(E e) {
        this.e = e;
    }
    public E get() {
        return e;
    }
}
class Derived extends Abstract<MyEnum> {
    public Derived() {
        super(MyEnum.A);
    }
    public static int sw(Derived derived) {
        switch (derived.get()) {
            case A: return 1;
            default: return 342;
        }
    }
}

你在使用什么特殊的编译器吗?

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1173290

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档