| Author |
upper bound wildcard is readonly but lower bound are not
|
Kartik Patel
Ranch Hand
Joined: Sep 12, 2005
Posts: 73
|
|
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
|
Chop your own wood, and it will warm you twice. - Henry Ford
|
 |
Rob Spoor
Sheriff
Joined: Oct 27, 2005
Posts: 19216
|
|
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.
|
SCJP 1.4 - SCJP 6 - SCWCD 5
How To Ask Questions How To Answer Questions
|
 |
Kartik Patel
Ranch Hand
Joined: Sep 12, 2005
Posts: 73
|
|
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
Joined: Oct 27, 2005
Posts: 19216
|
|
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
Joined: Sep 12, 2005
Posts: 73
|
|
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
Joined: Oct 27, 2005
Posts: 19216
|
|
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
Joined: Sep 12, 2005
Posts: 73
|
|
|
Thanks Rob. The explanation was quite informative.
|
 |
 |
|
|
subject: upper bound wildcard is readonly but lower bound are not
|
|
|