Can anybody tell me when is the actual type of <T> determined by the compiler for the method meth()? If it is at LINE#1 then as per my understanding the cast at LINE#2 in method meth() from Float to Byte should fail as Byte IS-NOT-A Float because the cast to type (T) would already have been resolved at compile time and thus this should generate a compile time error? But the code compiles and happily prints the output. What am i missing here?
You're assuming that there's runtime type checking of the contents of the list itself, but that's simply not true. Generics work by erasure, which means (in essence) that the compiler enforces certain type restrictions, but at runtime, the types have been erased; the List itself works only with Object references. You're tricking the compiler by using that type wildcard. If you tried to take that Float out of the list from within main, the compiler will have inserted a cast to String, and you'd get a runtime exception at that point.
With method-local generics, the method call determines the actual type. For instance, Collections.emptySet() returns a Set<String> if the reference type the value is assigned to is Set<String>. In your example, it is LINE#1 that determines that T is Byte.
As EFH said, during runtime there is no more T so the cast is basically (Object). Because your example can cause problems the compiler warns you - casting to T is highly discouraged, and your example shows exactly why. That's a ClassCastException waiting to happen once you retrieve the Float object but assign it to a Byte reference.
Sorry guys for posting a bit late. I was on a vacation
Thanks for your answers. i have a doubt.
Originally posted by Ernest-Friedman Hill:
If you tried to take that Float out of the list from within main, the compiler will have inserted a cast to String, and you'd get a runtime exception at that point.
The cast would not be a String but to a Byte as the list1 is a List of Bytes. Isn't it?
Suppose if i change the invocation on LINE#1 as
new Test().meth(list);// LINE#1 then what would be the generic type T resolved to? Is it Object ? I guess not because it is only Number which satisfies the construct <T extends Number> so it should be Number
o.k. that implies if I change <T extends Number> to <T> then the generic Type T would be resolved to an Object.
Moreover, the argument to meth(List<?> type) can accept a List of objects of any type. This makes it inappropriate to use in combination with generic type declaration of <T extends Number> as adding anything to a collection of generic type T declared within the method meth() can result in type unsafe addition as LINE#1 in original code shows.
Thanks guys for chipping in.