Java 如何解决返回泛型枚举的方法的不兼容上限错误

Java 如何解决返回泛型枚举的方法的不兼容上限错误,java,generics,enums,Java,Generics,Enums,我提供了一个接口来定义具有反向查找功能的枚举的行为: public interface Enumerable { public String getName(); public <E extends Enum<E>> E getByName(String name); } 当我尝试将getByName(String name)的return值分配给特定enum类型的变量时,我得到了以下错误:“不兼容的类型:推理变量E具有不兼容的上限java.lang.e

我提供了一个
接口
来定义具有反向查找功能的
枚举
的行为:

public interface Enumerable {
    public String getName();
    public <E extends Enum<E>> E getByName(String name);
}
当我尝试将
getByName(String name)
return
值分配给特定
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());

    .....
}
public final List getsubnumoptions(最终可枚举子菜单){
//这里是我得到错误的地方
子菜单sm=SubMenu.getByName(SubMenu.getName());
.....
}

您传递的参数属于可枚举类型

类型本身不是泛型的,它只有一个泛型方法

泛型方法定义其返回类型为某个(未知)枚举类型

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


现在,您尝试将其分配给类型为
子菜单
的特定变量。由于“未知枚举”可能是世界上的任何枚举,因此如果不进行类型转换,就无法将其分配给特定类型的变量
子菜单
。返回的真正类型可能确实是
子菜单
,但由于
可枚举
不是泛型,编译器无法知道这一点。

您应该使用额外的类型参数增强
可枚举
接口签名

public interface Enumerable<E extends Enum<E>> {

    public String getName();

    public E getByName(String name);    
}
公共接口可枚举{
公共字符串getName();
公共E getByName(字符串名称);
}
并相应地调整代码的其余部分:

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(“选项”),
菜单选项2(“另一个选项”;
私有最终字符串本地化名称;
专用子菜单(最终字符串本地化名称){
this.localizedName=localizedName;
}
@凌驾
公共字符串getName(){
返回此.localizedName;
}
@凌驾
公共子菜单getByName(最终字符串pName){
对于(子菜单:值()){
if(menu.name().equals(pName)
||menu.localizedName.equals(pName)){
返回菜单;
}
}
返回null;
}    
}
公共类ClientClass{
/**
*如果显式地将泛型E与子菜单交换,则此方法可以与子菜单一起使用
*/
公共E GetSubMenu选项(最终可枚举子菜单){
E sm=submenu.getByName(submenu.getName());
返回sm;
}
}

我想这是一个愚蠢的问题,但你确定你的编译错误与你声明的局部变量
子菜单
与你的方法参数
子菜单
同名无关吗?嗨,我的问题是打字错误。我的IDE中的源代码没有那个错误。我的问题已经更新。所以我接受了你认为静态查找映射也是一个坏主意吗?我要尝试一下这个解决方案。我想这就是我要寻找的。我很快就会回来接受这个答案。我忽略了映射,因为它具有完全相同的功能,每个枚举都是单独提供的。你可以像你一样通过名称轻松地寻址枚举值将从任何类调用一个静态的final常量。无论如何,如果您觉得从中受益,您当然可以实现它。
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;
    }
}