关于Java Generics操作的奇怪问题

zjf*_*fdu 2 java generics

下面的代码显示我可以在Map中插入不兼容的类型,但是当我无法从中检索元素时.在下面的例子中,我可以将两个整数放入Map中,但如果我取消注释最后两行,我将得到ClassCastException.这是JDK的错误,或者我错过了什么,因为我记得Java通用保证我们不能将不兼容的类型插入到泛型集合类中.

公共类HelloWorld {

private static class MapResultExtractor<K, V> {

    public Map<K, V> extract(Iterator<List<Object>> iter)
            throws IOException {
        Map<K, V> map = new HashMap<K, V>();
        while (iter.hasNext()) {
            List<Object> tuple = iter.next();
            K key = (K) (tuple.get(0) == null ? null : tuple.get(0));
            V value = (V) (tuple.get(1) == null ? null : tuple.get(1));
            map.put(key, value);
        }

        return map;
    }

}

public static void main(String[] args) throws IOException {
    MapResultExtractor<String, Integer> extractor = new MapResultExtractor<String, Integer>();
    List<Object> subList = new ArrayList<Object>();
    subList.add(1);
    subList.add(2);

    List<List<Object>> list = new ArrayList<List<Object>>();
    list.add(subList);

    Map<String, Integer> map = extractor.extract(list.iterator());
    for (Map.Entry<String, Integer> entry : map.entrySet()) {
       // System.out.println(entry.getKey().getClass() + "\t"
       //         + entry.getValue().getClass());
    }
}
Run Code Online (Sandbox Code Playgroud)

}

Vic*_*kin 10

编译器无法在这里查看

K key = (K) (tuple.get(0) == null ? null : tuple.get(0));
Run Code Online (Sandbox Code Playgroud)

你真的传递了类型的对象K(你真的传递了Integer而不是String).所以编译器信任你.

在运行时级别有类型擦除,所以当该行执行时,没有K,而是有

Object key = (tuple.get(0) == null ? null : tuple.get(0));
Run Code Online (Sandbox Code Playgroud)

只有这样你才真正尝试使用Integer值而不是String in println,运行时可以检测到类型不匹配.

解?使用Iterator<List<K>>而不是Iterator<List<Object>>作为你的extract()方法的参数(那么,在当前版本中,你将被迫返回Map<K, K>而不是Map<K, V>,这就是重点).

同样,代码的问题在于您强制将Integer视为对象(这是合法的)并强制将对象转换为类型K(在编译期间始终是合法的,并且在运行时并不总是正确的).