泛型:为什么实现的集合返回一个对象而不是指定的类型?

时间:2013-11-20 08:02:43

标签: java generics

我正在尝试使用自定义MapEntries实现OrderedMapEntry列表 - 因为我需要一个带有Vectors的自定义解决方案我不能使用TreeMap(http://docs.oracle.com/javase/7/docs/api/java/util/TreeMap.html)。我实现了一个没有任何错误的自定义列表,但是当我在增强的for循环中使用OrderedMapEntries类时,它返回Object

  • 使用增强型for循环时,如何确保类型安全?我的实施在确保这种类型安全方面做错了什么?

    public class OrderedMapEntries<K, V> implements Iterator, Iterable{
    
        private Vector<MapEntry<K, Vector<V>>> vector;
        private int vectorIndex;  // initializes with -1
    
        class MapEntry<A, B extends AbstractList<V>> implements Iterator, Iterable{
            // MapEntry implementation
    
        public void insert(int index, K key, Vector<V> vec){
            MapEntry<K, Vector<V>> mapEntry = new MapEntry<>(key, vec);
            vector.add(index, mapEntry);
        }
    
        @Override
        public MapEntry<K, Vector<V>> next(){
            vectorIndex++;
            return vector[vectorIndex]; 
        }
    }
    

我尝试使用增强的for循环遍历集合,但是它失败了,因为next()返回一个Object而不是我指定的元素。

OrderedMapEntries<Integer, String> ome = new OrderedMapEntries<>();
// I filled it with some test data

for (OrderedMapEntries<Integer, String>.MapEntry<Integer, Vector<String>> entry : ome){
    ; 
    }

2 个答案:

答案 0 :(得分:11)

您正在实施Iterable,原始类型,而不是Iterable<K>Iterable<V>。如果省略这样的类型参数,则iterator的签名变为 -

Iterator iterator();

返回Iterator,而非Iterator<K>Iterator<V>,其next方法将具有如下所示的签名 -

Object next();

这就是为什么你在增强的for循环中获得Object的原因,因为它在内部调用Iterator的{​​{1}}来获取下一个元素。

如果您使用这样的原始类型,几乎永远无法确保正确的类型安全。有关详细信息,请查看Effective Java,第23项 - 不要在新代码中使用原始类型

此外,您的next课程应该只实施OrderedMapEntries(请查看ArrayList如何执行此操作)。在其中实现Iterable<E>方法,使其返回适当的iterator到增强的for循环。

答案 1 :(得分:2)

您正在实施IteratorIterable的原始类型。首先,你应该从不实现它们。其次,如果要实现其中之一,请实现泛型类型而不是原始类型。这是一个显示How to implement iterable的示例。