• 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
  • Jeanne Boyarsky
  • Ron McLeod
  • Paul Clapham
  • Liutauras Vilda
Sheriffs:
  • paul wheaton
  • Rob Spoor
  • Devaka Cooray
Saloon Keepers:
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
  • Frits Walraven
  • Tim Moores
Bartenders:
  • Mikalai Zaikin

Why generic wildcard could bypass the type safety?

 
Greenhorn
Posts: 18
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hello,

I understand why this case doesn't work. And indeed it's a compile error of "Cannot cast from List<Integer> to List<Number>".



However, I don't understand why changing the childList to use wildcard could work. I am more confused by the childList could even add and print a non-integer. Does it violate the type safety?


Thank you.
 
Marshal
Posts: 79151
377
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Sounds like the thing about Cage<Animal> Cage<Lion> and Cage<Butterfly> in the Java Tutorials: Here: look for "wildcards".
 
author
Posts: 23951
142
jQuery Eclipse IDE Firefox Browser VI Editor C++ Chrome Java Linux Windows
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Why generic wildcard could bypass the type safety?



The assigment to a generic wildcard does not bypass the type safety. It is the next line, where you cast the list to something else, that broke the type check.

Henry
 
L Yan
Greenhorn
Posts: 18
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I understand why we could not add an element to List<? extends Number>. It is illegal to do:



That's why I do (List<Number>)childList. What I don't understand why it doesn't throw ClassCastException when parentList.add(3.14). Because the underlying list is a ArrayList<Integer> and 3.14 is not a integer, when Java tries to implicitly convert 3.14 to integer, is it a ClassCastException?



Act
 
Sheriff
Posts: 22781
131
Eclipse IDE Spring VI Editor Chrome Java Windows
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Because both references regard the contents as Number, and 3.14 is a Double, and therefore also a Number. It would fail if you would cast the list back to a List<Integer>.
 
Henry Wong
author
Posts: 23951
142
jQuery Eclipse IDE Firefox Browser VI Editor C++ Chrome Java Linux Windows
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

I understand why we could not add an element to List<? extends Number>. It is illegal to do:



So you understand that adding is "illegal"? But why is it "illegal"? Because it can violate the type safety !!


That's why I do (List<Number>)childList. What I don't understand why it doesn't throw ClassCastException when parentList.add(3.14). Because the underlying list is a ArrayList<Integer> and 3.14 is not a integer, when Java tries to implicitly convert 3.14 to integer, is it a ClassCastException?



Generics is only at compile time. ClassCastExceptions happen at runtime, when the generic type has already been erased.


IOWs, if you use generics, try your best to *not* cast anything... you need to let the generic do it's work.

Henry
 
L Yan
Greenhorn
Posts: 18
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Henry Wong wrote:
IOWs, if you use generics, try your best to *not* cast anything... you need to let the generic do it's work.
Henry



I definitely agree with you. I don't really want to do cast List<? extends Number> to List<Number>. But it doesn't seem that I have other choice. I have this set of API:



SomeFactory class is responsible to create a instance of BasePOJO's subclass and populate the data using the template. The ABC class is responsible to return an appropriate instance of SomeFactory according to the pojo Class passed in. And XYZ class actually uses the SomeFactory to create an instance of BasePOJO's subclass. For example, BasePOJO could be Animal. Then we could have SomeFactory<Cat> and SomeFactory<Dog>. If we do XYZ.generate(Cat cat), it would retrieve SomeFactory<Cat> and use SomeFactory<Cat>.createByTemplate(Cat catTemplate) to get a Cat instance.

The problem is: this.getABC().getFactory(pojo.getClass()) returns a SomeFactory<? extends BasePOJO> instead of SomeFactory. So I could not call SomeFactory<? extends BasePOJO>.create(pojo). It's compile error.

"The method createByTemplate(capture#2-of ? extends BasePOJO) in the type SomeFactory<capture#2-of ? extends BasePOJO> is not applicable for the arguments (BasePOJO)"

That's why I do:


Please let me know your suggestion how to make this design better and if possible how to avoid casting generic. Thank you very much.

I am not sure whether this question is still falling into the original
thread. I could start a new thread if necessary.
 
Henry Wong
author
Posts: 23951
142
jQuery Eclipse IDE Firefox Browser VI Editor C++ Chrome Java Linux Windows
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

But it doesn't seem that I have other choice.



That's fine..... But you are complaining that generics can't detect the type correctly, when you are forcing the type.

And BTW, if you are getting "errors" because the type is wrong -- after you forced the type -- doesn't that tell you that generics was right in not allowing the operation?

Henry
 
L Yan
Greenhorn
Posts: 18
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Henry Wong wrote:

And BTW, if you are getting "errors" because the type is wrong -- after you forced the type -- doesn't that tell you that generics was right in not allowing the operation?

Henry



I agree with you that it's not because generic is wrong that I have to cast the a generic type to a non-generic type. I guess the question in my previous thread is how to update the design to use the generic correctly and avoid any manual casting. Thank you very much for your reply.

reply
    Bookmark Topic Watch Topic
  • New Topic