Search code examples
javagenericsreferencegeneric-collectionsraw-types

Why can a raw type reference refer to a generic instance?


Please help understand why

Map map1 = new HashMap<String,String>(); // This compiles
Map<Object,Object> map2 = new HashMap<String,String>(); // This does not.

As per my understanding

Map map1 

is same as

Map<Object,Object> map1 

---- Edit ----

When generics are not provided for reference map1 , compiler accepts the object creation with any generics. This to me seemed like map1 have implicit

<Object,Object> 

generics applied.

So the question here is why compilation fails when map2 have explicit

<Object,Object> 

generics applied.

For downvoters , the question for which this is marked as duplicate , does not answer my question directly.

Thanks Chetan and Pham , That explains!!!.


Solution

  • Map<Object,Object> map2 = new HashMap<String,String>();

    As per my understanding

    Map map1 is same as

    Map<Object,Object> map1

    No. A Map is not the same as a Map<Object,Object>.

    A reference of type HashMap<T,T> is a subtype of a reference of type Map. In other words, a reference of type Map can refer to an object of type HashMap<String,String>.

    On the other hand, a reference of type HashMap<T,T> is not a subtype of a reference of type Map<E,E> (Even if T is-a E and HashMap is-a Map). In other words, a reference of type Map<Object,Object> can't refer to an object of type HashMap<String,String> even if String is-a Object and HashMap is-a Map.

    If you are wondering why the rules for reference sub types in case of generics works this way, there is one explanation I can give based on my understanding. Generics are syntactic sugar and go through what is known as type-erasure once the code is compiled. That is, a HashMap<String,String> when compiled becomes a HashMap.

    If the compiler allowed the statement Map<Object,Object> map = new HashMap<String,String>, it would mislead programmers to believe that the Map can only hold String key and values at runtime. This would be absurd since Generics go through type-erasure at compile time itself.

    The statement Map map = new HashMap<String,String> is allowed on the other hand mostly for backward compatibility with legacy code.