Maaf, tetapi Anda tidak bisa.
Deklarasi wildcard List<? extends Number> foo3
berarti bahwa variabel foo3
dapat menyimpan nilai apa pun dari keluarga jenis (bukan nilai apa pun dari jenis tertentu). Ini berarti bahwa semua ini adalah penugasan legal:
List<? extends Number> foo3 = new ArrayList<Number>; // Number "extends" Number
List<? extends Number> foo3 = new ArrayList<Integer>; // Integer extends Number
List<? extends Number> foo3 = new ArrayList<Double>; // Double extends Number
Jadi, mengingat ini, jenis objek apa yang bisa Anda tambahkan List foo3
yang akan sah setelah salah satu dari ArrayList
penugasan di atas :
- Anda tidak dapat menambahkan
Integer
karena foo3
bisa menunjuk sebuah List<Double>
.
- Anda tidak dapat menambahkan
Double
karena foo3
bisa menunjuk pada a List<Integer>
.
- Anda tidak dapat menambahkan
Number
karena foo3
bisa menunjuk pada a List<Integer>
.
Anda tidak dapat menambahkan objek apa pun List<? extends T>
karena Anda tidak dapat menjamin jenis apaList
yang benar-benar mengarah, sehingga Anda tidak dapat menjamin bahwa objek tersebut diizinkan List
. Satu-satunya "jaminan" adalah bahwa Anda hanya dapat membacanya dan Anda akan mendapatkan T
atau subkelas dari T
.
Logika balik berlaku untuk super
, misalnyaList<? super T>
. Ini legal:
List<? super Number> foo3 = new ArrayList<Number>; // Number is a "super" of Number
List<? super Number> foo3 = new ArrayList<Object>; // Object is a "super" of Number
Anda tidak dapat membaca jenis T tertentu (misalnya Number
) List<? super T>
karena Anda tidak dapat menjamin jenis apa List
yang benar-benar mengarah. Satu-satunya "jaminan" yang Anda miliki adalah Anda dapat menambahkan nilai tipeT
(atau subkelas apa pun T
) tanpa melanggar integritas daftar yang ditunjuk.
Contoh sempurna dari ini adalah tanda tangan untuk Collections.copy()
:
public static <T> void copy(List<? super T> dest,List<? extends T> src)
Perhatikan bagaimana src
deklarasi daftar digunakan extends
untuk memungkinkan saya untuk melewati Daftar apa pun dari keluarga tipe Daftar terkait dan masih menjamin itu akan menghasilkan nilai tipe T atau subkelas dari T. Tapi Anda tidak dapat menambahkan ke src
daftar.
The dest
penggunaan daftar deklarasi super
untuk mengizinkan saya untuk lulus Daftar apapun dari keluarga jenis Daftar terkait dan masih menjamin aku bisa menulis nilai dari jenis tertentu T ke daftar itu. Tetapi tidak dapat dijamin untuk membaca nilai-nilai tipe T tertentu jika saya membaca dari daftar.
Jadi sekarang, berkat wildcard generik, saya dapat melakukan semua panggilan ini dengan metode tunggal:
// copy(dest, src)
Collections.copy(new ArrayList<Number>(), new ArrayList<Number());
Collections.copy(new ArrayList<Number>(), new ArrayList<Integer());
Collections.copy(new ArrayList<Object>(), new ArrayList<Number>());
Collections.copy(new ArrayList<Object>(), new ArrayList<Double());
Pertimbangkan kode yang membingungkan dan sangat luas ini untuk melatih otak Anda. Baris yang dikomentari adalah ilegal dan alasan mengapa dinyatakan pada ujung kanan garis (perlu menggulir untuk melihat beberapa di antaranya):
List<Number> listNumber_ListNumber = new ArrayList<Number>();
//List<Number> listNumber_ListInteger = new ArrayList<Integer>(); // error - can assign only exactly <Number>
//List<Number> listNumber_ListDouble = new ArrayList<Double>(); // error - can assign only exactly <Number>
List<? extends Number> listExtendsNumber_ListNumber = new ArrayList<Number>();
List<? extends Number> listExtendsNumber_ListInteger = new ArrayList<Integer>();
List<? extends Number> listExtendsNumber_ListDouble = new ArrayList<Double>();
List<? super Number> listSuperNumber_ListNumber = new ArrayList<Number>();
//List<? super Number> listSuperNumber_ListInteger = new ArrayList<Integer>(); // error - Integer is not superclass of Number
//List<? super Number> listSuperNumber_ListDouble = new ArrayList<Double>(); // error - Double is not superclass of Number
//List<Integer> listInteger_ListNumber = new ArrayList<Number>(); // error - can assign only exactly <Integer>
List<Integer> listInteger_ListInteger = new ArrayList<Integer>();
//List<Integer> listInteger_ListDouble = new ArrayList<Double>(); // error - can assign only exactly <Integer>
//List<? extends Integer> listExtendsInteger_ListNumber = new ArrayList<Number>(); // error - Number is not a subclass of Integer
List<? extends Integer> listExtendsInteger_ListInteger = new ArrayList<Integer>();
//List<? extends Integer> listExtendsInteger_ListDouble = new ArrayList<Double>(); // error - Double is not a subclass of Integer
List<? super Integer> listSuperInteger_ListNumber = new ArrayList<Number>();
List<? super Integer> listSuperInteger_ListInteger = new ArrayList<Integer>();
//List<? super Integer> listSuperInteger_ListDouble = new ArrayList<Double>(); // error - Double is not a superclass of Integer
listNumber_ListNumber.add(3); // ok - allowed to add Integer to exactly List<Number>
// These next 3 are compile errors for the same reason:
// You don't know what kind of List<T> is really
// being referenced - it may not be able to hold an Integer.
// You can't add anything (not Object, Number, Integer,
// nor Double) to List<? extends Number>
//listExtendsNumber_ListNumber.add(3); // error - can't add Integer to *possible* List<Double>, even though it is really List<Number>
//listExtendsNumber_ListInteger.add(3); // error - can't add Integer to *possible* List<Double>, even though it is really List<Integer>
//listExtendsNumber_ListDouble.add(3); // error - can't add Integer to *possible* List<Double>, especially since it is really List<Double>
listSuperNumber_ListNumber.add(3); // ok - allowed to add Integer to List<Number> or List<Object>
listInteger_ListInteger.add(3); // ok - allowed to add Integer to exactly List<Integer> (duh)
// This fails for same reason above - you can't
// guarantee what kind of List the var is really
// pointing to
//listExtendsInteger_ListInteger.add(3); // error - can't add Integer to *possible* List<X> that is only allowed to hold X's
listSuperInteger_ListNumber.add(3); // ok - allowed to add Integer to List<Integer>, List<Number>, or List<Object>
listSuperInteger_ListInteger.add(3); // ok - allowed to add Integer to List<Integer>, List<Number>, or List<Object>
List<? extends Number>
tidak berarti "daftar objek dari berbagai jenis, yang semuanya meluasNumber
". Ini berarti "daftar objek dari tipe tunggal yang memanjangNumber
".