Untuk memahami kovarians dan kontravarians, kita mesti terlebih dahulu memperkenalkan:
Menurut prinsip penggantian Liskov, jika C ialah subkelas P, maka P boleh menggantikan C, iaitu P p = baharu C();
C mewarisi daripada P, dilambangkan sebagai C bd7e92f34f372a599ec1c0ccf8180590 Tiada hubungan pewarisan denganListc0f559cc8d56b43654fcbe4aa9df7b4a
Apakah kovarians
Jika F ialah kovarian, apabila C 3a440e4d2aee916c100d5cacb62b5f4c boleh Dilihat sebagai kelas induk
ArrayListc0f559cc8d56b43654fcbe4aa9df7b4a
,
? extend Number
boleh dilihat sebagai julat jenis, mewakili subkelas Nombor tertentu Tatasusunanialah kovarian secara lalai
Number[] numbers = new Integer[3];Apakah kontravarian
Jika F adalah kontravarian, apabila C 621b939a379cdc6041efa6fae5c32674= F(P)
Java menyediakan super untuk menukar invarian kepada kovarians, contohnya:
List<? super Number> list = new ArrayList<Object>(1); //correntPada masa ini,
Listda50108ad159903fabe211f1543600e8
boleh dianggap sebagai kelas induk bagiArrayLista87fdacec66f0909fc0757c19f2d2b1d
melanjutkan dan super
Pertama, mari kita lihat pelaksanaan Collection.add:
public interface List<E> extends Collection<E> { boolean add(E e); }Adakah kod berikut melaporkan ralat?
? extends Number
tidak sepadan dengan jenisInteger
List<? extends Number> list = new ArrayList<Integer>(); // correct list.add(Integer.valueOf(1)); //errorPertama, apabila memanggil kaedah tambah,
E
generik secara automatik menjadia2b037db85f4e1df0e812b9647ac55a8
dan ralat dilaporkan pada baris kedua. Dengan kata lain,
? extends Number
bukan kelas indukInteger
. Di sini kita perlu membezakan bahawaLista2b037db85f4e1df0e812b9647ac55a8
ialah kelas indukArrayListc0f559cc8d56b43654fcbe4aa9df7b4a
.
? extends Number
boleh dianggap sebagai jenis tertentu dalam julat jenis, mewakili subkelas Nombor tertentu, tetapi tidak jelas subkelas mana ia mungkin Terapung, mungkin Pendek atau ia mungkin Subkelas (Integer diubah suai oleh muktamad, tidak ada subkelas yang mungkin, ini hanyalah situasi hipotesis), ia hanya menentukan sempadan atasnya sebagai Nombor, dan tidak menentukan sempadan bawah (mungkin terdapat? extends Number
<. ;Integer
) , oleh itu? extends Number
bukan kelas indukInteger
Ubah suai sedikit kod di atas dan ia akan betul:
List<? super Number> list = new ArrayList<Object>(); // correct list.add(Integer.valueOf(1)); //correctPertama daripada semua, kerana penyongsangan,
Listda50108ad159903fabe211f1543600e8
ialah Kelas indukArrayLista87fdacec66f0909fc0757c19f2d2b1d
, baris pertama adalah betul.Baris kedua:
? super Number
ialah kelas indukInteger
, sebabnya ialah:? super Number
mewakili kelas induk Nombor tertentu, ia mungkinSerializable
atauObject
tetapi tidak kira yang mana satu , kelas induk Nombor mestilah kelas induk Integer, jadi baris kedua juga betulPerlukah saya menggunakan extends atau super? java.util.Collections (JDK1.7 ) memberi kami jawapan:
public static <T> void copy(List<? super T> dest, List<? extends T> src) { int srcSize = src.size(); if (srcSize > dest.size()) throw new IndexOutOfBoundsException("Source does not fit in dest"); if (srcSize < COPY_THRESHOLD || (src instanceof RandomAccess && dest instanceof RandomAccess)) { for (int i=0; i<srcSize; i++) dest.set(i, src.get(i)); } else { ListIterator<? super T> di=dest.listIterator(); ListIterator<? extends T> si=src.listIterator(); for (int i=0; i<srcSize; i++) { di.next(); di.set(si.next()); } } }Apabila anda ingin mendapatkan data daripada kelas generik, gunakan extends; >
- Untuk mendapatkan data daripada kelas generik Semasa menulis data dalam kelas, gunakan super; kad bebas (iaitu, lanjutan atau super tidak digunakan)
private static <E> E getFirst(List<? extends E> list){ return list.get(0); } private static <E> void setFirst(List<? super E> list, E firstElement){ list.add(firstElement); } public static void main(String[] args) { List<Integer> list = new ArrayList<Integer>(); setFirst(list, 1); Number number = getFirst(list); }
Atas ialah kandungan terperinci Kaedah kovarian, kontravarian, lanjutan dan pemilihan super generik Java. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!