如何为返回通用枚举的方法解决不兼容的上限错误

时间:2014-10-23 13:47:48

标签: java generics enums

我给了interface来定义具有反向查找功能的enums的行为:

public interface Enumerable {
    public String getName();
    public <E extends Enum<E>> E getByName(String name);
}

这是enum implements interface

public enum SubMenu implements Enumerable {

    SIMPLE_MENU("An Option");

    private final String name;

    public static final Map<String,SubMenu> lookup = new HashMap<>();

    static {
        for (SubMenu subMenu : EnumSet.allOf(SubMenu.class)) {
            lookup.put(subMenu.getName(), subMenu);
        }
    }

    private SubMenu(final String name) {
        this.name = name;
    }

    public final String getName() { return name; }

    public SubMenu getByName(String name) {
        return lookup.get(name);
    }
}

当我尝试将return getByName(String name)值分配给特定enum类型的变量时,我收到此错误:“不兼容的类型:推理变量E具有不兼容的上限java.lang.Enum中,子菜单”。如何解决此错误?

public final List<Enumerable> getSubMenuOptions(final Enumerable subMenu) {

    //Here is where I get the error
    SubMenu sm = subMenu.getByName(subMenu.getName());

    .....
}

2 个答案:

答案 0 :(得分:2)

您应该使用其他类型参数

增强Enumerable接口签名
public interface Enumerable<E extends Enum<E>> {

    public String getName();

    public E getByName(String name);    
}

并相应地调整其余代码:

public enum SubMenu implements Enumerable<SubMenu> {

    MENU_OPTION_1("An Option"),
    MENU_OPTION_2("Another Option";

    private final String localizedName;

    private SubMenu(final String localizedName){
        this.localizedName = localizedName;
    }

    @Override
    public String getName() {
        return this.localizedName;
    }

    @Override
    public SubMenu getByName(final String pName) {
        for(SubMenu menu : values()){
            if(menu.name().equals(pName) 
                    || menu.localizedName.equals(pName)){
                return menu;
            }
        }
        return null;
    }    
}

public class ClientClass{

    /**
     * This method can work with SubMenu, if you explicitly exchange the generic E with SubMenu
     */
    public <E extends Enum<E>> E getSubMenuOptions(final Enumerable<E> submenu){
        E sm = submenu.getByName(submenu.getName());

        return sm;
    }
}

答案 1 :(得分:0)

您传递的参数是Enumerable类型。

类型本身不是通用的,它只是一个通用的方法。

泛型方法定义其返回类型是某种(未知)枚举类型。

因此,当您致电subMenu.getByName(submenu.getName())时,结果的类型基本上是“未知的枚举”。

现在,您尝试将此值分配给SubMenu类型的特定变量。由于“未知的枚举”可能是世界上的任何枚举,因此您无法在没有类型转换的情况下将其分配给特定类型SubMenu的变量。返回的真实类型实际上可能是SubMenu,但由于Enumerable不是通用的,编译器无法知道这一点。