Java Generics puzzle - 获取泛型类型的对象类/类型,以便稍后确保类型

时间:2015-05-22 22:23:56

标签: java generics

看看这个短班。

它做什么?它是一个HashMap,其中键是一个Class对象,值是一个Hashmap,其键和值由Class对象定义。

假设你想要一个方法add(K obj),这将是一个方便的方法。你为什么要强迫用户输入add(Person.class,personInstance),当你也可以让他只是传递实例本身时 - 代码应该能够获取对象的类并将实例放在键下面对象的类。但我不能。 add(K obj)便捷方法无法编译:

public class TypedHashmap extends HashMap<Class, HashMap> {

    public <K> HashMap<K, K> getHashMap(Class<K> type) {
        return (HashMap<K, K>) getOrDefault(type, new HashMap<K, K>());
    }

    public <K> void add(K obj, Class<K> type) {
        HashMap<K, K> toModify = getHashMap(type);
        toModify.put(obj, obj);
    }

    public <K> void add(K obj) {
        add(obj, obj.getClass());
    }
}

编译错误:

enter image description here

我可以看到Java不确定obj.getClass()类型。但我不明白为什么。是因为它不能确保该类实际上不是扩展K的东西吗?这里有什么问题?这可以以某种方式解决吗?

3 个答案:

答案 0 :(得分:3)

泛型是确保类型安全的工具。

您设计API的方式是类型对此级别安全,这就是您收到此错误的原因。

public <K> void add(K obj) {
    add(obj, (Class<K>) obj.getClass());
}

是否明确表示您无法确保此处的类型安全。或者只是做一个

public void add(Object obj) {
    add(obj, (Class<Object>) obj.getClass());
}

这将为您提供相同级别的类型安全(无)。

如果你想要一个稍微清洁的解决方案(在简单的添加功能中没有强制转换),你也必须修改你的其他添加功能。

public <K> void add(K obj, Class<? super K> type) {
    HashMap<K, K> toModify = getHashMap(type);
    toModify.put(obj, obj);
}

public void add(Object obj) {
    add(obj, obj.getClass());
}

但最后我相信你正在实施反模式

问题在于:

Number a = new Integer(3);
map.add(a);
map.getHashMap(Number.class).contains(a);

产生错误。 Number地图中的整数。因为您的地图不支持子类型和继承。

Integer对象添加到列表中。但除非我知道哪个

答案 1 :(得分:1)

就编译器而言obj.getClass()返回类型为Class<?>的实例,并且您没有带签名的方法

void add(K obj, Class<?> type)

你有

void add(K obj, Class<K> type)

虽然很接近,但并不完全正确。

答案 2 :(得分:1)

您没有使您的类具有通用性,因此所有方法泛型都是独立的(每个K都是不同的ANY)。我想你想要像

这样的东西
public class TypedHashmap<K> extends HashMap<Class<K>, HashMap<K, Class<K>>> {
    public HashMap<K, Class<K>> getHashMap(Class<K> type) {
        return (HashMap<K, Class<K>>) getOrDefault(type, new HashMap<>());
    }

    public void add(K obj, Class<K> type) {
        HashMap<K, Class<K>> toModify = getHashMap(type);
        toModify.put(obj, type);
    }

    public void add(K obj) {
        add(obj, (Class<K>) obj.getClass());
    }
}