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

194 views Asked by At

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!!!.

2

There are 2 answers

3
Chetan Kinger On BEST ANSWER

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.

0
Codebender On

That is because when you use new HashMap<String,String>(); the object can contain only String values.

But the variable Map<Object,Object> map2 means that map2 can contain Object keys and values.

And using Map<Object, Object> is not the same as using Map. Its just that in the latter you are not using type safety, the former will show your errors during compilation itself but the latter will throw errors during Runtime.