简体   繁体   中英

Using Java Generics Bounded Type Arguments

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:

  1. Is using bounded type arguments a right approach?
  2. If Yes, What type of elements can it contain in the scenario explained above.
  3. Can you throw in an example, where bounded type arguments are useful or the right scenario/way to implement them.

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM