Üzgünüm ama yapamazsın.
Joker karakter bildirimi List<? extends Number> foo3, değişkenin foo3bir tür ailesinden herhangi bir değeri tutabileceği anlamına gelir (belirli bir türün herhangi bir değeri yerine). Bu, bunlardan herhangi birinin yasal görevler olduğu anlamına gelir:
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
Dolayısıyla, List foo3buna göre, yukarıdaki olası ArrayListgörevlerden herhangi birinden sonra buna ne tür bir nesne ekleyebilirdiniz :
- Bir ekleyemezsiniz
Integerçünkü foo3bir işaret olabilir List<Double>.
- Ekleyemezsiniz
Doubleçünkü a foo3işaret ediyor olabilir List<Integer>.
- Ekleyemezsiniz
Numberçünkü a foo3işaret ediyor olabilir List<Integer>.
Herhangi bir nesneyi ekleyemezsiniz List<? extends T>çünkü ne tür bir nesneyi Listgerçekten gösterdiğini garanti edemezsiniz, böylece nesneye izin verildiğini garanti edemezsiniz List. Tek "garanti" sadece ondan okuyabilir ve bir Tveya alt sınıf alırsınız T.
Ters mantık super, ör List<? super T>. Bunlar yasal:
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
Belirli bir T türünü (örn. Number) Okuyamazsınız , List<? super T>çünkü Listbunun ne tür olduğuna işaret edemezsiniz . Sahip olduğunuz tek "garanti" , işaret edilen listenin bütünlüğünü ihlal etmeden Tbir tür (veya herhangi bir alt sınıfı T) değeri ekleyebilmenizdir .
Bunun mükemmel bir örneği aşağıdakilerin imzasıdır Collections.copy():
public static <T> void copy(List<? super T> dest,List<? extends T> src)
srcListe bildiriminin extends, ilgili Liste türlerinin bir ailesinden herhangi bir Listeyi geçirmeme ve yine de T türünün veya T alt sınıflarının değerlerini üreteceğini garanti etmem için nasıl kullandığına dikkat edin . Ancak srclisteye eklenemezsiniz .
destListesi bildirimi kullanımları superbeni ilişkili Liste türlerinin bir aileden herhangi Listesini geçmesine izin ve hala o listeye belirli tip T değerini yazabilirsiniz garanti etmek. Ama değerlerini okumak için garanti edilemez spesifik ben listeden okursanız tipi T.
Şimdi, genel joker karakterler sayesinde, bu çağrılardan herhangi birini bu tek yöntemle yapabilirim:
// 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());
Beyninizi egzersiz için bu kafa karıştırıcı ve çok geniş kodu düşünün. Yorum yapılan satırlar yasa dışıdır ve satırın en sağında belirtilme nedeni (bazılarını görmek için kaydırmanız gerekir):
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>"tümü genişleyen farklı türdeki nesnelerin listesi" anlamına gelmediğini unutmayınNumber. "Genişleyen tek tip nesnelerin listesi" anlamına gelirNumber.