使用枚举键和不同值类型映射

时间:2015-04-20 17:11:08

标签: java generics dictionary collections enums

我想在Java中定义地图,哪些键是枚举,以及值的类型取决于键。例如,假设我们有以下枚举类型:

enum KeyType {
        HEIGHT(Integer.class),
        NAME(String.class),
        WEIGHT(Double.class)
       // constructor and getter for Class field

}

和一些地图:

Map< KeyType, Object > map = new EnumMap<>(KeyType.class);

是否有任何简单而安全的方法来编写泛型方法:

public < T > T get(KeyType key) {
//...
}

将从该地图获取值并将其转换为与类类相对应的颜色?

3 个答案:

答案 0 :(得分:2)

UPDATE !!!: 考虑到这一点:

enum KeyType {

    //your enums ...
    private final Class val;

    //constructor ...

    //and generic(!) access to the class field:
    <T> Class<T> val() {
        return val;
    }
}

......这是可能的:

public <T> T get(KeyType key) {
    return (T) key.val().cast(map.get(key));
}

答案 1 :(得分:0)

您的地图定义需要

Map< KeyType, ?> map = new EnumMap<>(KeyType.class);

如果您将Object指定为通用类型,则只允许Object的实际实例,而不是子类型。

我不相信有任何直接的,通用的方式(没有双关语意)去做你想做的事。您需要创建一些映射函数,根据枚举将对象转换为正确的类型。

答案 2 :(得分:0)

你无法使用枚举。但是你可以编写一个“假的”枚举(Java代码在Java 1.5之前使用私有构造函数和公共静态实例的方式),并将泛型类型附加到每个常量:

import java.io.Serializable;
import java.util.Map;

public final class KeyType<T>
implements Serializable {
    private static final long serialVersionUID = 1;

    public static final KeyType<Integer> HEIGHT =
        new KeyType<>("HEIGHT", Integer.class);

    public static final KeyType<String> NAME =
        new KeyType<>("NAME", String.class);

    public static final KeyType<Double> WEIGHT =
        new KeyType<>("WEIGHT", Double.class);

    private static final KeyType<?>[] allValues = {
        HEIGHT, NAME, WEIGHT
    };

    /** @serial */
    private final String name;

    /** @serial */
    private final Class<T> type;

    private KeyType(String name,
                    Class<T> type) {
        this.name = name;
        this.type = type;
    }

    public String name() {
        return name;
    }

    public Class<T> getType() {
        return type;
    }

    @Override
    public String toString() {
        return name();
    }

    public static KeyType<?>[] values() {
        return allValues.clone();
    }

    public static KeyType<?> valueOf(String name) {
        for (KeyType<?> value : allValues) {
            if (value.name.equals(name)) {
                return value;
            }
        }
        throw new IllegalArgumentException("No such value: \"" + name + "\"");
    }

    @Override
    public boolean equals(Object obj) {
        return (obj instanceof KeyType &&
            this.name.equals(((KeyType<?>) obj).name));
    }

    @Override
    public int hashCode() {
        return name.hashCode();
    }

    public T getValue(Map<KeyType<?>, ?> map) {
        return type.cast(map.get(this));
    }
}