1

Is there a reason why Eclipse reports type safety warning in the following declaration?

Map<String,List<Map<String, ParseNode>>> mapX = new HashMap();

I understand that all mapX usages would be strongly typed but what can possibly be achieved by java generics insisting on providing HashMap paramaterized type (other than adding noise to the code)?

Paul Bellora
  • 54,340
  • 18
  • 130
  • 181
Tegiri Nenashi
  • 3,066
  • 2
  • 19
  • 20

3 Answers3

5

Your declaration is invalid.

Using Generics (Parameterized Types)

Using Java 5 to 6, you should write:

Map<String, List<Map<String, ParseNode>>> m =
    new HashMap<String, List<Map<String, ParseNode>>>();

Starting with Java 7, you can simplify this with:

Map<String, List<Map<String, ParseNode>>> m = new HashMap<>();

Your syntax means something different and uses a raw type:

Map<String, List<Map<String, ParseNode>>> m = new HashMap();

Update:

To answer your question, this has implications (as mentioned by the Java Tutorial):

Note that to take advantage of automatic type inference during generic class instantiation, you must specify the diamond. [In your case] the compiler generates an unchecked conversion warning because the HashMap() constructor refers to the HashMap raw type, not the [parameterized Map] type.

Basically meaning that the parameterization of your type here doesn't have much meaning. The code following this declaration will be compiled with the assumptation that it contains values with the types as declared. However at runtime, you declared a type of a raw type, and you could very well have assigned a map containing different values to this entry.

What you wrote would be the equivalent of writing something like:

Map rawMap = new HashMap();
rawMap.add("string", "not list!");

Map<String, List<Map<String, ParseNode>>> m = rawMap; // uh oh!!

Which would compile fine, and blow up in your face at runtime when you try to access one of m's values as a List<Map<String, ParseNode>>.

Reasons

The reason for this is that Generics where introduced while conserving complete backwards compatibility at the source level, hence some of their limitation, like:

  • the impossibility to have a short-hand form without at least some indicator for generics support (here, the so-called diamond operator <>),
  • the impossibility to inspect generic-types at runtime, because they had to be implemented with Type Erasure.

Further Reading

Community
  • 1
  • 1
haylem
  • 22,460
  • 3
  • 67
  • 96
  • Is difference between raw type and parameterized type something that can get me into trouble in this kind of situation? Let me add that the declaration is final. – Tegiri Nenashi Mar 02 '12 at 22:57
  • @TegiriNenashi: Read the linked section of the Java Tutorial **Type Inference and Instantiation of Generic Classes** and you have the answer to your question in just a few lines. – haylem Mar 02 '12 at 23:00
  • Your references are helpful, yet the example is not realistic. Isn't it reasonable to assume that virtually all programmers after learning generics would never declare objects of raw types? What I'm saying is that how much compiler effort does it take to figure out that constructor with no arguments won't cause any mismatching type problems? – Tegiri Nenashi Mar 02 '12 at 23:37
  • @TegiriNenashi: First, regarding _"Isn't it reasonable to assume that virtually all programmers after learning generics would never declare objects of raw types?"_, don't overestimate lazyness and stupidity. Second, apparently quite a lot of effort, I'm afraid. It's not that it wouldn't be possible if the language was brand new. It's not possible because generics didn't exist before in Java (which is why you don't have this issue in languages that didn't need to ensure backwards bytecote compatibility). – haylem Mar 02 '12 at 23:41
  • @TegiriNenashi: Maybe Goetz explains this better than me in the [Generics Gotchas](http://www.ibm.com/developerworks/java/library/j-jtp01255/index.html), sections **The Road Not Taken**, **Generifying Existing Classes** and **Implications of Erasure**. – haylem Mar 02 '12 at 23:44
0

Following code similar to yours:

List strs = new ArrayList();
strs.add("foo");
List<Integer> ints = strs;

I think it is quite obvious that this is not typesafe.

  • No it is not: I use parametrized declarations. – Tegiri Nenashi Mar 02 '12 at 23:27
  • @TegiriNenashi: Yes, but what Biggerskimo tried to show is that your parameterized types here have only impacts where they can be checked against something. See my answer for more detail, or the Java Tutorial. – haylem Mar 02 '12 at 23:38
-1

Java 7 does not require that anymore, but Java 5 & 6 do. I am guessing that you have set your project compiler compliance level to 1.5 or 1.6.

Guillaume Polet
  • 47,259
  • 4
  • 83
  • 117