【问题标题】:Java Enum as generic type in EnumJava Enum 作为 Enum 中的泛型类型
【发布时间】:2013-09-15 07:08:06
【问题描述】:

我正在尝试在以我自己的 Enum 作为参数的抽象类中创建一个抽象方法。但我也希望 Enum 是通用的。

所以我这样声明:

public abstract <T extends Enum<T>> void test(Enum<T> command);

在实现中,我将枚举作为那个:

public enum PerspectiveCommands {
    PERSPECTIVE
}

方法声明变为:

@Override
public <PerspectiveCommands extends Enum<PerspectiveCommands>> void test(Enum<PerspectiveCommands> command) {

}

但如果我这样做:

@Override
public <PerspectiveCommands extends Enum<PerspectiveCommands>> void test(Enum<PerspectiveCommands> command) {
    if(command == PerspectiveCommands.PERSPECTIVE){
        //do something
    }
}

我无法访问 PerspectiveCommands.PERSPECTIVE 并出现错误:

cannot find symbol symbol: variable PERSPECTIVE   location: class Enum<PerspectiveCommands> where PerspectiveCommands is a type-variable: PerspectiveCommands extends Enum<PerspectiveCommands> declared in method <PerspectiveCommands>test(Enum<PerspectiveCommands>)

我做了一个这样的解决方法:

public <T extends Enum<T>> byte[] executeCommand(Enum<T> command) throws Exception{
    return executeCommand(command.name());
}

@Override
protected byte[] executeCommand(String e) throws Exception{
    switch(PerspectiveCommands.valueOf(e)){
        case PERSPECTIVE:
            return executeCommand(getPerspectiveCommandArray());
        default:
            return null;
    }
}

但我想知道是否可以不通过我的解决方法?

【问题讨论】:

    标签: java generics methods enums


    【解决方案1】:

    在您的方法实现中PerspectiveCommands 不是枚举,而是您的类型参数,通常称为T。因此,它会遮蔽同名的枚举,如 axtavt 已经说过的,因此 PERSPECTIVE 在这里是未知的。

    您的抽象方法声明很好,但您可以使用稍微不同的方法。

    public void test(PerspectiveCommands command) 不起作用,因为此方法不会覆盖通用版本。原因是泛型版本的类型是从参数中推断出来的,因此您可以传递任何枚举。

    但是,我假设您有一个定义抽象方法的接口或抽象类。所以尝试这样的事情:

    interface TestInterface<T extends Enum<T>>
    {
      public abstract void test(T command);
    }
    
    class TestImpl implements TestInterface<PerspectiveCommands>
    {
      @Override
      public void test(PerspectiveCommands command) {
        if(command == PerspectiveCommands.PERSPECTIVE){
            //do something
        }
      }
    }
    

    【讨论】:

    【解决方案2】:

    @mike 的答案是正确的方法。

    public interface Command1 {
    }
    
    public enum MyCommand1 implements Command1 {
    }
    
    abstract <E extends Enum<E> & Command1> void execute(E command);
    

    另一个版本来了

    // intending to be used only on enums
    public interface Command2<E extends Enum<E>> extends Command1 {
    }
    
    public enum MyCommand2 implements Command2<MyCommand2> {
    }
    
    abstract <E extends Enum<E> & Command2<E>> execute(E command);
    

    【讨论】:

    • 谢谢。而且对于编辑,不知道&lt;!-- language: java --&gt; 就像您使用自引用类型边界的方法一样。有时这真是一件好事。最近在模拟退火实现中使用它。仅供参考stackoverflow.com/a/18657788/1809463
    【解决方案3】:

    正如@axtavt 已经指出的那样,问题在于阴影。

    如果您希望您的代码按原样工作,您可以更改类型变量的名称以消除阴影。

    public <C extends Enum<C>> void test(Enum<C> command)
    

    我还将向类型边界添加一个接口,只允许命令枚举,而不是每个枚举派生类的实例。

    public <C extends Enum<C> & CommandInterface> void test(Enum<C> command)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-07-16
      • 2022-01-14
      • 1970-01-01
      • 1970-01-01
      • 2022-07-07
      • 1970-01-01
      • 2023-04-02
      • 1970-01-01
      相关资源
      最近更新 更多