Java Enum as generic type in Enum

102,726

Solution 1

In your method implementation PerspectiveCommands is 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 PERSPECTIVE is unknown here.

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.

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

Solution 2

@mike's answer is the way to go.

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

Solution 3

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

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)
Share:
102,726
Garcia Julien
Author by

Garcia Julien

Updated on November 22, 2020

Comments

  • Garcia Julien
    Garcia Julien over 3 years

    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.

    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.PERSPECTIVE with the error:

    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?

  • Thomas
    Thomas over 10 years
    @GarciaJulien here's some info on shadowing: xyzws.com/Javafaq/what-is-variable-hiding-and-shadowing/15 There are also a number of questions on variable or method shadowing here on SO. It's definitely useful to know what shadowing is. :)
  • mike
    mike over 10 years
    Thx. And also for the edit, did not know about that <!-- language: java --> Like your approach with the self-referential type boundary. Sometimes it's a really nice thing. Used it in a simulated annealing implementation lately. FYI stackoverflow.com/a/18657788/1809463