Difference between <? extends T> and <? super T> and PECS principle
The wildcard(萬用字元) declaration ofList<? extends Number> foo3
means that any of these are legal assignments:
List<? extends Number> foo3 = new ArrayList<Number>(); // Number "extends" Number (in this context) List<? extends Number> foo3 = new ArrayList<Integer>(); // Integer extends NumberList<? extends Number> foo3 = new ArrayList<Double>(); // Double extends Number
-
Reading- Given the above possible assignments, what type of object are you guaranteed to read from
List foo3
:- You can read a
Number
because any of the lists that could be assigned tofoo3
contain aNumber
or a subclass ofNumber
- You can't read an
Integer
becausefoo3
could be pointing at aList<Double>
. - You can't read a
Double
becausefoo3
could be pointing at aList<Integer>
.
- You can read a
-
Writing- Given the above possible assignments, what type of object could you add to
List foo3
that would be legal forallthe above possibleArrayList
- You can't add an
Integer
becausefoo3
could be pointing at aList<Double>
. - You can't add a
Double
becausefoo3
could be pointing at aList<Integer>
. - You can't add a
Number
becausefoo3
could be pointing at aList<Integer>
.
- You can't add an
You can't add any object toList<? extends T>
because you can't guarantee what kind ofList
it is really pointing to, so you can't guarantee that the object is allowed in thatList
. The only "guarantee" is that you can only read from it and you'll get aT
or subclass ofT
.
Now considerList <? super T>
.
The wildcard declaration ofList<? super Integer> foo3
means that any of these are legal assignments:
List<? super Integer> foo3 = new ArrayList<Integer>(); // Integer is a "superclass" of Integer (in this context) List<? super Integer> foo3 = new ArrayList<Number>(); // Number is a superclass of Integer List<? super Integer> foo3 = new ArrayList<Object>(); // Object is a superclass of Integer
-
Reading- Given the above possible assignments, what type of object are you guaranteed to receive when you read from
List foo3
:- You aren't guaranteed an
Integer
becausefoo3
could be pointing at aList<Number>
orList<Object>
. - You aren't guaranteed a
Number
becausefoo3
could be pointing at aList<Object>
. - Theonlyguarantee is that you will get an instance of an
Object
or subclass ofObject
(but you don't know what subclass).
- You aren't guaranteed an
-
Writing- Given the above possible assignments, what type of object could you add to
List foo3
that would be legal forallthe above possibleArrayList
assignments:- You can add an
Integer
because anInteger
is allowed in any of above lists. - You can add an instance of a subclass of
Integer
because an instance of a subclass ofInteger
is allowed in any of the above lists. - You can't add a
Double
becausefoo3
could be pointing at anArrayList<Integer>
. - You can't add a
Number
becausefoo3
could be pointing at anArrayList<Integer>
. - You can't add an
Object
becausefoo3
could be pointing at anArrayList<Integer>
.
- You can add an
PECS
RememberPECS:"Producer Extends, Consumer Super".
-
"Producer Extends"- If you need a
List
to produceT
values (you want to readT
s from the list), you need to declare it with? extends T
, e.g.List<? extends Integer>
. But you cannot add to this list. -
"Consumer Super"- If you need a
List
to consumeT
values (you want to writeT
s into the list), you need to declare it with? super T
, e.g.List<? super Integer>
. But there are no guarantees what type of object you may read from this list. -
If you need to both read from and write to a list, you need to declare it exactly with no wildcards, e.g.
List<Integer>
.
?是萬用字元 extends T 和 super T 是上邊界(最高的粗略父類)和下邊界(最低的詳細子類)
那麼為什有邊界呢?
因為泛型集合裡物件元素間有繼承關係,但泛型集合裡之間是沒有繼承關係的。
<? extends T>和<? super T>的出現就是為了解決這個問題。
<? extend T >不影響往外取,但不能往裡存。因為編譯器不知道下限,不知道存入規則。
<? super T>不影響往裡存,但取只能放在Object物件裡。因為編譯器不知道上限,所以元素的型別資訊就丟失。