When compiled with javac -Xlint (nonstardard option for turning on all warnings), the following output is spit out to console:
Java generics was introduced in Java 1.5 and is heavily used in modern Java. The question is: why should we always use types in generic classes?
Let’s illustrate this using an code snippet from Effective Java:
As you can imagine, compiling and running this results in the following:
In Angelika Langer’s FAQ, another possible type of warning is pointed out to be possible to happen:
She explains that
“A cast whose target type is either a (concrete or bounded wildcard) parameterized type or a type parameter is unsafe, if a dynamic type check at runtime is involved. At runtime, only the type erasure is available, not the exact static type that is visible in the source code. As a result, the runtime part of the cast is performed based on the type erasure, not on the exact static type.”
In the example, the cast to Wrapper would check whether the object returned from super.clone is a Wrapper, not whether it is a wrapper with a particular type. Similarly, the casts to the type parameter T are cast to type Object at runtime, and probably optimized away altogether. Due to type erasure, the runtime system is unable to perform more useful type checks at runtime.
Another point to this is to mention how generics in Java are implemented. Java language implements generics via principle called type erasure. This is basically a dirty hack which is done at compile time - all the generics are erased by the compiler (and compiler adds casts to the generic type where necessary). To demonstrate this further, consider this Java source code and its appropriate bytecode:
Output of javap -c UncheckedChecker:
What we naturally expect from compiler when type erasure is present in the language architecture is that compiler refuses to compile code with generics which breaks type safety. Consider this simple example:
It should be obvious that adding object of type java.lang.String should be an illegal operation as java.lang.String is not a subtype of Stamp.
For completeness sake, here is the compiler output: