Java 具有泛型类型枚举的泛型枚举

Java 具有泛型类型枚举的泛型枚举,java,Java,我有以下接口和类定义 interface A { } class B { public static enum C implements A { c1, c2, c3; } public static enum D implements A { d1, d2, d3; } public static enum E implements A { e1, e2, e3; }

我有以下接口和类定义

interface A
{
}

class B
{
    public static enum C implements A
    {
        c1, c2, c3;
    }

    public static enum D implements A
    {
        d1, d2, d3;
    }

    public static enum E implements A
    {
        e1, e2, e3;
    }
}
现在我有了一个类,在这个类中我声明了一个映射,并将枚举指定为键并设置了一个值

class Test
{
    private Map<C, String> myMap;

    public void assignVal()
    {
        myMap = new EnumMap<C, String>(C.class);
        myMap.put(C.c1, String.valueOf(1));
    }
}
类测试
{
私人地图myMap;
公共无效赋值()
{
myMap=新的EnumMap(C.class);
myMap.put(C.c1,String.valueOf(1));
}
}
问题:正如您所看到的,myMap与枚举C绑定。我想创建myMap的通用版本,以便在类B中分配任何枚举值

我已经去过stackoverflow邮局了: 试试这个:

private Map<Enum<? extends A>, String> myMap;

私有映射&A>
,但更易于键入。

您不能使用
EnumMap
执行此操作

EnumMap需要一个单一类型的键-构造函数通过将泛型类型绑定到具体类型来强制实现这一点

在引擎盖下,它构建了一个可能的键值缓存,用于强制执行运行时类型安全


如果希望允许层次结构中的键,则需要使用另一种类型的映射。

我同意teppic的说法——不能将
EnumMap
一般用于
A
的所有子类。必须使用特定的混凝土等级建造。请参阅EnumMap的JavaDoc

我看你似乎有两个选择

使用其他类型的映射实现(例如
HashMap

实现
A
的另一个子类,以便可以使用
EnumMap

Map<A, String> myMap1 = new HashMap<>();
myMap1.put(C.c1, C.c1.name());
System.out.println(myMap1);
如果出于某些原因,您确实想使用
EnumMap
,但您不想使用 要将
C
D
E
的所有值实现到一个枚举中,您仍然需要 下面的解决方案

实现一个新的
a
子类(在下面的代码示例中称之为
supercode
),该子类具有
C
D
E
,以及 它有一个静态方法
getsupercode()
,用作桥接:

public static enum SuperCde implements A{
    c1,c2,c3,
    d1,d2,d3,
    e1,e2,e3
    ;

    public static SuperCde getSuperCde(A a) {
        if (a instanceof C) {
            C cValue = (C) a;
            switch (cValue) {
            case c1: return SuperCde.c1;
            case c2: return SuperCde.c2;
            case c3: return SuperCde.c3;
            default: throw new IllegalArgumentException();              
            }
        } else if (a instanceof D) {
            D dValue = (D) a;
            switch (dValue) {
            case d1: return SuperCde.d1;
            case d2: return SuperCde.d2;
            case d3: return SuperCde.d3;
            default: throw new IllegalArgumentException();              
            }
        } else if (a instanceof E) {
            E eValue = (E) a;
            switch (eValue) {
            case e1: return SuperCde.e1;
            case e2: return SuperCde.e2;
            case e3: return SuperCde.e3;
            default: throw new IllegalArgumentException();              
            }
        } else {
            throw new IllegalArgumentException();
        }
    }
}
然后您可以使用以下代码:

Map<SuperCde, String> myMap2 = new EnumMap<SuperCde, String>(SuperCde.class);       
myMap2.put(SuperCde.getSuperCde(C.c1), C.c1.name());
System.out.println(myMap2);

正如其他人指出的,您不能使用
EnumMap
。另外,在使用
有效时,有界通配符
&A>
的版本不存在。考虑到这一点,您可以使用使用
构造执行静态类型检查的对象包装映射键

class EnumAWrapper{
    final Enum<?> enumObj;
    final A aObj;

    <E extends Enum<E> & A> EnumAWrapper(E enumA){
        enumObj = enumA;
        aObj = enumA;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((aObj == null) ? 0 : aObj.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        EnumAWrapper other = (EnumAWrapper) obj;
        if (aObj == null) {
            if (other.aObj != null)
                return false;
        } else if (!aObj.equals(other.aObj))
            return false;
        return true;
    }

}
类枚举说话者{
最终枚举enumObj;
最终A aObj;
EnumAWrapper(E enumA){
enumObj=enumA;
aObj=enumA;
}
@凌驾
公共int hashCode(){
最终整数素数=31;
int结果=1;
result=prime*result+((aObj==null)?0:aObj.hashCode();
返回结果;
}
@凌驾
公共布尔等于(对象obj){
if(this==obj)
返回true;
if(obj==null)
返回false;
如果(getClass()!=obj.getClass())
返回false;
EnumAWrapper其他=(EnumAWrapper)对象;
if(aObj==null){
if(other.aObj!=null)
返回false;
}else如果(!aObj.equals(other.aObj))
返回false;
返回true;
}
}
下面是一个演示:

Map<EnumAWrapper, String> map = new HashMap<>();

//does compile
map.put(new EnumAWrapper(C.c1), "");
map.put(new EnumAWrapper(D.d1), "");
map.put(new EnumAWrapper(E.e1), "");
A aObj = map.keySet().iterator().next().aObj;
Enum<?> enumObj = map.keySet().iterator().next().enumObj;

//does not compile (given that enum F does not implement A)
map.put(new EnumAWrapper(new A(){}), "");
map.put(new EnumAWrapper(F.f1), "");
Map Map=newhashmap();
//编译
地图放置(新的枚举器(C.c1),“”);
地图放置(新编号rapper(D.d1)),;
地图放置(新的枚举器(E.e1),“”);
A aObj=map.keySet().iterator().next().aObj;
Enum enumObj=map.keySet().iterator().next().enumObj;
//不编译(假定枚举F未实现A)
put(新的enumawraper(新的A(){}),“”);
地图放置(新的EnumAWrapper(F.f1),“”);

真的吗?不是
?扩展枚举&A
?这看起来不起作用,因为
Enum
@andy上的边界是相同的:看到了吗,但是你能用上界键类型放入一个映射吗?不能
put()
Map@Andreas就像我说的,这意味着键不是
A
类型。例如,
A=myMap.keySet().iterator().next()
是一个编译错误。为什么不直接使用
Map
new HashMap()
?@Andreas可能
a
有其他实现。
class EnumAWrapper{
    final Enum<?> enumObj;
    final A aObj;

    <E extends Enum<E> & A> EnumAWrapper(E enumA){
        enumObj = enumA;
        aObj = enumA;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((aObj == null) ? 0 : aObj.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        EnumAWrapper other = (EnumAWrapper) obj;
        if (aObj == null) {
            if (other.aObj != null)
                return false;
        } else if (!aObj.equals(other.aObj))
            return false;
        return true;
    }

}
Map<EnumAWrapper, String> map = new HashMap<>();

//does compile
map.put(new EnumAWrapper(C.c1), "");
map.put(new EnumAWrapper(D.d1), "");
map.put(new EnumAWrapper(E.e1), "");
A aObj = map.keySet().iterator().next().aObj;
Enum<?> enumObj = map.keySet().iterator().next().enumObj;

//does not compile (given that enum F does not implement A)
map.put(new EnumAWrapper(new A(){}), "");
map.put(new EnumAWrapper(F.f1), "");