I have a Box
class as shown below.
public class Box <E> {
private List<E> itmes = new ArrayList<>();
public void addItem(E e){
itmes.add(e);
}
public void addItemList(List<? extends E> itemList){
itmes.addAll(itemList);
}
public List<E> getItems(){
return itmes;
}
}
The first implementation uses unbounded type arguments, which works fine. As shown below
Box<Apple> appleBox = new Box<>();
Apple fujiApple = new Apple("fujiApple");
Apple kashmiriApple = new Apple("kashmiriApple");
appleBox.addItem(fujiApple);
appleBox.addItem(kashmiriApple);
Box<Orange> orangeBox = new Box<>();
Orange weirdOrange = new Orange("weirdOrange");
Orange orangeOrange = new Orange("orangeOrange");
orangeBox.addItem(weirdOrange);
orangeBox.addItem(orangeOrange);
Box<Fruit> fruitBoxAll = new Box<>();
fruitBoxAll.addItemList(appleBox.getItems());
fruitBoxAll.addItemList(orangeBox.getItems());
But now, I want to use bounded type argument as shown below
Box<? extends Fruit> fruitBox = new Box<>();
Declaring ? extends Fruit
? extends Fruit
as type argument means that List
inside Box
class will also be of type ? extends Fruit
? extends Fruit
. And following code will give an error
fruitBox.addItem(fujiApple);
As at some point later, user may try to add oranges to the same list
fruitBox.addItem(orangeOrange);
which is not right. So I cannot use this bounded type argument object to create a Box
of sub-type of Fruit
. Which is understandable from Java point of view, but then using bounded type arguments seem not useful.
So from the implementation perspective, I have following questions:
As others have pointed out what you're doing is covered by the PECS idea - Produce Extends, Consumer Super. You should really read Difference between <? super T> and <? extends T> in Java
Your problem with List is that the list is declared as some type which is a specific subclass of Fruit but you're trying to treat it as a list of Fruit, which is not typesafe.
Where it's useful to use the ? extends Fruit
? extends Fruit
bounded type is when you're returning a list to a client who will a) only ever try to read from the list and b) who only cares that objects in the list implement the Fruit
interface.
eg
public void myMethod() {
List<? extends Fruit> myList = theListProducingMethod();
for (Fruit f: myList) {
f.fruitMethod();
}
}
public List<? extends Fruit> theListProducingMethod() {
final List<Orange> someList = new ArrayList<>();
someList.add(new Orange());
return someList;
}
The thing to note here is that the returned list is effectively immutable in myMethod
. Because its generic type is <? extends Fruit>
<? extends Fruit>
there's no way to call myList.add
in myMethod
in a type safe fashion.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.