Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generics: Why the implemented collections returns an object instead of the specified type?

Tags:

java

generics

I am trying to implement an OrderedMapEntry list with custom MapEntries - as I need a custom solution with Vectors I cannot use a TreeMap(http://docs.oracle.com/javase/7/docs/api/java/util/TreeMap.html). I implemented a custom list without any errors, but when I use the OrderedMapEntries class in an enhanced for loop it returns an Object.

  • How can I ensure type safety when using an enhanced for loop? What my implementation is doing wrong in ensuring this type safety?

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

I tried to iterate over the collection with an enhanced for loop, but it fails as next() returns an Object and not my specified element.

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

for (OrderedMapEntries<Integer, String>.MapEntry<Integer, Vector<String>> entry : ome){
    ; 
    }
like image 949
Jon Avatar asked Dec 11 '22 09:12

Jon


2 Answers

You are implementing Iterable, a raw type, not Iterable<K> or Iterable<V>. If you omit type parameter like this, then the signature of iterator becomes -

Iterator iterator();

which returns an Iterator, not Iterator<K> or Iterator<V>, whose next method will have a signature like below -

Object next();

This is the reason why you are getting Object in the enhanced for loop, as it internally calls the Iterator's next to get the next element.

You can almost never ensure proper type safety if you use raw types like this. For more information, please check out Effective Java, Item 23 - Don't use raw types in new code.

Also, your OrderedMapEntries class should only implement Iterable<E> (please check out how ArrayList does this). Implement the iterator method in it such that it returns an appropriate Iterator<E> to the enhanced for loop.

like image 103
MD Sayem Ahmed Avatar answered May 18 '23 00:05

MD Sayem Ahmed


You're implementing the raw types of Iterator and Iterable. Firstly, you should never implement both of them. Secondly, if you want to implement one of them, implement the generic type as opposed to the raw type. Here's an example showing How to implement iterable.

like image 24
Steve P. Avatar answered May 18 '23 01:05

Steve P.