• 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:
  • Tim Cooke
  • Campbell Ritchie
  • paul wheaton
  • Ron McLeod
  • Devaka Cooray
Sheriffs:
  • Jeanne Boyarsky
  • Liutauras Vilda
  • Paul Clapham
Saloon Keepers:
  • Tim Holloway
  • Carey Brown
  • Piet Souris
Bartenders:

upper bound wildcard is readonly but lower bound are not

 
Ranch Hand
Posts: 73
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Why upper bound wildcard generics make the collection readonly but same not apply for lower bound wildcard collection?

List<? extends Number> l= new ArrayList<Integer>();
Number n1= new Double(1.0);
l.add(n1) // won't compile

List<? super Double> l= new ArrayList<Number>();
Number n1= new Double(1.0);
Double n2= new Double(1.0);
l.add(n1) // won't compile
l.add(n2) // will compile
 
Sheriff
Posts: 22849
132
Eclipse IDE Spring Chrome Java Windows
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
With List<? extends Number>, you can't add anything because you don't know which Number subclass you can actually add. Is this list in fact List<Integer>, List<Double>, List<Float>? You don't know! Therefore, you can't add a Double - it might break the rules for the list.

With List<? super Double>, you know that the generic type is a Double or any of its super classes - Number or Object. So let's consider the options:
List<Double> - no problem in adding a Double here
List<Number> - a Double is a Number, so no problem here either
List<Object> - anything is an object, so no problem here either


When retrieving it's the other way around. With List<? extends Number>, you don't know what the type is, except that it is Number or a sub class. Therefore, you can safely assign any element to a Number reference. With List<? super Double>, you don't know what type it actually is; you have three options. You can't assume it's a Double or a Number, so you can only assign it to Object references without explicit casting.
 
Kartik Patel
Ranch Hand
Posts: 73
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Originally posted by Rob Prime:


With List<? super Double>, you know that the generic type is a Double or any of its super classes - Number or Object. So let's consider the options:
List<Double> - no problem in adding a Double here
List<Number> - a Double is a Number, so no problem here either
List<Object> - anything is an object, so no problem here either



I think adding List<Number> and List<Object> won't compile in case of List<? super Double>. Only List<Double> will compile. Please try.
 
Rob Spoor
Sheriff
Posts: 22849
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
I was not talking about adding the lists, but adding a Double to any of these types. In code:

Compiles without a problem.
 
Kartik Patel
Ranch Hand
Posts: 73
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I am talking about this. See following tree
Vehicle
Honda Tata
City Civic Indigo Indica

Check this:

class Vehicle {}
class Honda extends Vehicle {}
class Tata extends Vehicle {}
class City extends Honda {}
class Civic extends Honda {}
class Indica extends Tata {}
class Indigo extends Tata {}

List<? super Honda> ls=null;

Honda honda=new Honda();
Civic civic=new Civic();
Vehicle vehicle=new Vehicle();


ls.add(honda); // Fine Honda super Honda
ls.add(civic); // ITS WORKING WHY??? civic is not super of Honda
ls.add(vehicle); // Its not WORKING WHY??? Vehicle super Honda right?


Please suggest..
 
Rob Spoor
Sheriff
Posts: 22849
132
Eclipse IDE Spring Chrome Java Windows
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Originally posted by Kartik Patel:
ls.add(honda); // Fine Honda super Honda
ls.add(civic); // ITS WORKING WHY??? civic is not super of Honda
ls.add(vehicle); // Its not WORKING WHY??? Vehicle super Honda right?


A Civic object will pass the "instanceof Honda" test so that is why you can add elements. You can't prevent this using generics - if a method can accept a Honda object, it can accept a Civic object too. The only thing you could do is checking exact class matching (if (civic.getClass() == Honda.class)).

Now why you cannot add a Vehicle object:
List<? super Honda> means that it could, in fact, be a List<Honda>. It could be a List<Vehicle> as well, but you don't know that. As far as adding goes, it IS a List<Honda>.

If you want to be able to add Vehicles, you need to declare the list to allow Vehicles:
- List<Vehicle>
- List<? super Vehicle>
- List<Object> // equals List<? super Object>

That will still allow Civics and Hondas though.


The super does not means that it accepts only super classes of Honda. It means that the type is Honda or a super class. And as I said before, anywhere you can use a Honda, you can use a Civic.

Similarly, List<? extends Honda> means that the type is Honda or a sub class. Therefore, you know that everything that is stored in it is at least a Honda; it might be a Civic, or an Indigo, you don't know that without runtime checking, but it is still a Honda. But since you don't know that type, you can't add any Honda object to it. Imagine you want to add a Civic but it is in fact a List<Indigo>. So much for your type safe List...


So the rule is as such, for any class X:
List<? super X> can add objects of X or a sub class. You can only retrieve elements as Object though; everything else needs to be cast.
List<? extends X> cannot have anything added at all. You can retrieve elements as X or any super class of X.
List<X> can add objects of X or a sub class. You can retrieve elements as X or any super class of X.


If you don't understand, please (re)read the Generics Trail of the Sun Java tutorial.
 
Kartik Patel
Ranch Hand
Posts: 73
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Thanks Rob. The explanation was quite informative.
 
Greenhorn
Posts: 10
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Thanks for posting responses that don't regurgitate the explanation found in the Oracle Java book, which I think is not clearly worded on this particular topic. I had the same problems understanding generics and wildcards and now get it.
 
Rob Spoor
Sheriff
Posts: 22849
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
You're welcome
 
Consider Paul's rocket mass heater.
reply
    Bookmark Topic Watch Topic
  • New Topic