Java Enum 作为 Enum 中的泛型类型

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18738133/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 10:36:34  来源:igfitidea点击:

Java Enum as generic type in Enum

javagenericsmethodsenums

提问by Garcia Julien

I'm trying to create an abstract method in a abstract class that takes my own Enum as argument. But I want also that that Enum will be generic.

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

So I declared it like that:

所以我这样声明:

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

In the implementation, I have en enum as that one:

在实现中,我有一个枚举:

public enum PerspectiveCommands {
    PERSPECTIVE
}

and the method declaration becomes:

方法声明变为:

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

}

But if I do:

但如果我这样做:

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

I don't have access to the PerspectiveCommands.PERSPECTIVEwith the error:

我无权访问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>)

I've made a workaround like this:

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

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;
    }
}

But I would like to know if it's possible to not pass by my workaround?

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

采纳答案by Thomas

In your method implementation PerspectiveCommandsis not the enum but your type parameter, which often is called T. It thus shadows the enum of the same name like axtavt already said, thus PERSPECTIVEis unknown here.

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

Your abstract method declaration is fine but you might use a slightly different approach.

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

public void test(PerspectiveCommands command)would not work, since this method would not override the generic version. The reason is that with the generic version the type is inferred from the parameter and thus you could pass any enum.

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

However, I assume you have an interface or abstract class which defines the abstract method. So try something like this:

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

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
    }
  }
}

回答by mike

As @axtavt already pointed out, the problem is the shadowing.

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

If you want your code to work as it is, you could change the name of the type variable to remove the shadowing.

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

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

I would also add an interface to the type boundary to just allow command enums and not an instance of every enum derived class.

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

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

回答by Jin Kwon

@mike's answer is the way to go.

@mike 的答案是要走的路。

public interface Command1 {
}

public enum MyCommand1 implements Command1 {
}

abstract <E extends Enum<E> & Command1> void execute(E command);

Here comes an another version

这是另一个版本

// 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);