• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Tim Cooke
  • Ron McLeod
  • paul wheaton
  • Jeanne Boyarsky
Sheriffs:
  • Paul Clapham
  • Devaka Cooray
Saloon Keepers:
  • Tim Holloway
  • Roland Mueller
  • Himai Minh
Bartenders:

Generics doubt

 
Ranch Hand
Posts: 231
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator


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?
 
author and iconoclast
Posts: 24207
46
Mac OS X Eclipse IDE Chrome
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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.
 
Sheriff
Posts: 22857
132
Eclipse IDE Spring Chrome Java Windows
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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.
 
Harvinder Thakur
Ranch Hand
Posts: 231
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
 
Sheriff
Posts: 9709
43
Android Google Web Toolkit Hibernate IntelliJ IDE Spring Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Taking the original code as base let me explain it to you.

Harvinder since the type of meth T is not used in the method except for the return type, so there are two ways that the type of T can be decided by the compiler.

1. By examining the type in which the return value is being catched. So if you write this

List<Byte> = new Test().meth(null);

then the compiler will know that the type of T is Byte. The other way is to use this syntax

new Test().<Byte>meth(null);

Now here too the compiler will be able find that the type of T is Byte.

But if you don't provide any information to the method, then the type of T will become Number as the declaration of meth defines <T extends Number>...
 
Harvinder Thakur
Ranch Hand
Posts: 231
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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.
 
With a little knowledge, a cast iron skillet is non-stick and lasts a lifetime.
reply
    Bookmark Topic Watch Topic
  • New Topic