• 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

Generics and Wildcards in Java

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


Question 1 : Why the compile error on the listWildcard.add() ?
You will probably answer me that this is because generics are "Type Safe".
“Type safe” in this case means that there will be no unexpected class cast exception, i.e. if a ClassCastException occurs, then it must be caused by an explicit cast in the code.
Can someone exemplify with a piece of additional code how could you break this "Type Safe" rule (that is having unexpected ClassCastException) if listWildcard.add() were allowed?

Question 2: Why is this rule not broken when adding two different types(Integer/Double) of object in list.add()
 
Bartender
Posts: 6109
6
Android IntelliJ IDE Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Bogdan Degeratu wrote:
Question 1 : Why the compile error on the listWildcard.add() ?



Because List<? extends Number> listWildcard says that listWildcard is a List of either Number or some particular type that extends Number. That is, listWildcard could be List<Number> or it could be List<Integer> or List<Double>, and we don't know any more about it than that.

So no matter what you try to add to it, the new element might be the wrong type.


Question 2: Why is this rule not broken when adding two different types(Integer/Double) of object in list.add()



Because list is List<Number>, so it can accept anything that is a Number.
 
Greenhorn
Posts: 25
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Here you have a piece of code that may break this "Type Safe" rule .... if the add call is allowed



 
Bartender
Posts: 10780
71
Hibernate Eclipse IDE Ubuntu
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Bogdan Degeratu wrote:Question 1 : Why the compile error on the listWildcard.add() ? ... Can someone exemplify with a piece of additional code how could you break this "Type Safe" rule (that is having unexpected ClassCastException) if listWildcard.add() were allowed?


I think others have already done that; however first you should also know what wildcards are used for. They are used as "placeholders".

Every instance of a generic class MUST have a specific type. Thus, you can say:

List<? extends Number> list = new ArrayList<Double>();

but you can't say:

List<? extends Number> list = new ArrayList<? extends Number>();

So when you look at them, imagine that the compiler is thinking "this is a List of some definite type, I just don't know what it is"; and in your particular case above, it's thinking "this is a List of some definite type that extends Number, I just don't know what it is".

If you can get your head around that, then you'll understand why it can't possibly allow you to add ANY type - even one that extends Number - because it may not match the actual type of the list it's trying to add to.

However, probably the easiest way to remember it is that wildcarded collections are read-only.

Question 2: Why is this rule not broken when adding two different types(Integer/Double) of object in list.add()


Because both Integer and Double are Numbers - it's just basic subclassing.

HIH

Winston
 
Bogdan Degeratu
Greenhorn
Posts: 4
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Thank you Winston & Andrei for clarifying the subject to me.

I think I got it wrong at the begining, thinking that both list and listWildcard declarations are similar.


I think I get it now :
means that list contains objects of type Number (or any subtype of Number)
whereas
means that listWildcard contains objects of type
Number (or any subtype of Number)
OR
Integer (or any subtype of Integer)
OR
Double (or any subtype of Double)
etc.
without knowing which one of these.

However, probably the easiest way to remember it is that wildcarded collections are read-only.


Only for upper bounded generics. It's the opposite (write-only) for lower bounded, right?


 
Greenhorn
Posts: 8
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
List<? extends Number> listDouble = new ArrayList<Double>();
List<? extends Number> listInt = new ArrayList<Integer>();
listDouble.add(new Integer(0));
listInt.add(new Double(0));

Hi In The Above code

i)? extends Number ========>We can use either Number Or it's child classes.But we don't know exact type that is y it is "?"

While we are adding an element to the list we can't specify which type of object exactly we are adding but we can add null to the listDouble & listInt objects like


listDouble.add(null);
listInt.add(null);
System.out.println(listDouble.get(0));
System.out.println(listInt.get(0));


Ok
 
Winston Gutkowski
Bartender
Posts: 10780
71
Hibernate Eclipse IDE Ubuntu
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Bogdan Degeratu wrote:Only for upper bounded generics. It's the opposite (write-only) for lower bounded, right?


You know what? I don't honestly know; mainly because I've never created a List<? super X> (and TBH, I can't imagine why you ever would).

I'd have to check the tutorials again, but my guess would be that you can always read an element into an Object, and the compiler is still going to complain about an add of anything that is not specifically an X, because the actual List type might not be compatible.

However, whether or not it's that smart in real life, I don't know: It's possible that, like upper bounded wildcards, it simply disallows them.

Winston
 
Marshal
Posts: 79061
375
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Winston Gutkowski wrote: . . . I'd have to check the tutorials again, . . .

If you google for “Angelika Langer Java generics FAQ”, you should find an alternative source of useful information.
 
Saloon Keeper
Posts: 15449
363
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Upper bounds are for producers of objects, lower bounds are useful for consumers.

Here is an example of a method that copies numbers from one list to another. The from list is the producer (of numbers), and the to list is the consumer.
Granted, this method is not very useful. However, a very common type of consumer is a Comparator. You will often find methods that look like this:
 
With a little knowledge, a cast iron skillet is non-stick and lasts a lifetime.
reply
    Bookmark Topic Watch Topic
  • New Topic