簡體   English   中英

具有通用類型枚舉的通用枚舉

[英]Generic Enum with generic type Enum

我有以下接口和類定義。

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

現在我有一個類,我聲明一個Map並將枚舉作為鍵並設置一個值。

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與枚舉C綁定。我想創建myMap的通用版本,因此我可以在B類中分配任何枚舉值。

我已經通過stackoverflow帖子: 如何使用泛型實現枚舉?

你不能用EnumMap做到這一點。

EnumMap需要一個單一類型的鍵 - 構造函數通過將泛型類型綁定到具體類型來強制執行此操作。

在引擎蓋下,它構建了一個可能的鍵值緩存,用於強制運行時類型安全。

如果要允許層次結構中的鍵,則需要使用其他類型的映射。

嘗試這個:

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

這將類型綁定到任何實現A的Enum。

這相當於<? extends Enum<?> & A> <? extends Enum<?> & A> ,但更容易輸入。

我會說teppic所說的 - 你不能將EnumMap一般用於A所有子類。 它必須用特定的具體類構建。 請參閱EnumMap的JavaDoc

https://docs.oracle.com/javase/7/docs/api/java/util/EnumMap.html

我看到你似乎有兩種選擇

使用其他類型的Map實現(例如HashMap

Map<A, String> myMap1 = new HashMap<>();
myMap1.put(C.c1, C.c1.name());
System.out.println(myMap1);

輸出將是:

{c1=c1}

實現A另一個子類,以便您可以使用EnumMap

如果由於某些原因,您確實想要使用EnumMap並且您不希望將CDE所有值都實現為一個枚舉,那么您仍然可以使用以下解決方案。

實現A的新子類(在下面的代碼示例中稱之為SuperCde ),它具有CDE所有可能值,並且它有一個靜態方法getSuperCde()作為橋接器:

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

輸出將是:

{c1=c1}

正如其他人所指出的,你不能使用EnumMap 此外,使用<E extends Enum<E> & A> ,有界通配符的版本<? extends Enum<?> & A> <? extends Enum<?> & A>不存在。 鑒於此,您可以使用<E extends Enum<E> & 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), "");

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM