Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

All HashMap type values erased in generic class?

Why does the following not compile? The compiler gives an error for the + sign in the print line.

public class Test<T> {
  HashMap<Integer,Integer> m = new HashMap<Integer, Integer>();
  public static void main(String[] args) {
    Integer zero1 = 0;
    Integer zero2 = 0;
    Test t = new Test();
    t.m.put(1,zero1);
    t.m.put(2,zero2);
    System.out.println(t.m.get(1)+t.m.get(2)==t.m.get(2));
  }
}

I understand type erasure, but m is a HashMap<Integer,Integer>, it should not depend on the type <T> at all. Why is the compiler rejecting this? Removing <T> in the first line allows compiling, but I don't see why this shouldn't work as well.

Is this a compiler bug or is there any logic behind such behavior?

like image 325
user1111929 Avatar asked Sep 27 '12 01:09

user1111929


People also ask

What is generic type erasure?

Type erasure is a process in which compiler replaces a generic parameter with actual class or bridge method. In type erasure, compiler ensures that no extra classes are created and there is no runtime overhead.

Why does Java do type erasure?

Generics were introduced to the Java language to provide tighter type checks at compile time and to support generic programming. To implement generics, the Java compiler applies type erasure to: Replace all type parameters in generic types with their bounds or Object if the type parameters are unbounded.

What are the two 2 types of Erasure?

- Erasure is a type of alteration in document. It can be classified as chemical erasure and physical erasure.

Can HashMap store different value types?

It stores the data in (Key, Value) pairs, and you can access them by an index of another type (e.g. an Integer). One object is used as a key (index) to another object (value).


1 Answers

I don't have an explanation why, but the behavior does seem to be correct-by-definition.§4.8 "Raw Types" of the Java Language Specification explicitly states that:

The type of a constructor (§8.8), instance method (§8.4, §9.4), or non-static field (§8.3) M of a raw type C that is not inherited from its superclasses or superinterfaces is the raw type that corresponds to the erasure of its type in the generic declaration corresponding to C.

In your example, the raw type C is Test (as opposed to Test<Object> or Test<Integer> or whatnot) and the non-static field M is m. As a result of the above rule, the type of t.m is the raw type HashMap, rather than HashMap<Integer, Integer>, so the return-type of t.m.get(Object) is Object rather than Integer.

like image 166
ruakh Avatar answered Oct 21 '22 06:10

ruakh