Rumah  >  Artikel  >  Java  >  Kaedah kovarian, kontravarian, lanjutan dan pemilihan super generik Java

Kaedah kovarian, kontravarian, lanjutan dan pemilihan super generik Java

PHPz
PHPzke hadapan
2023-05-26 13:46:121292semak imbas

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 dengan Listc0f559cc8d56b43654fcbe4aa9df7b4a

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 Tatasusunan

ialah 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);  //corrent

Pada masa ini, Listda50108ad159903fabe211f1543600e8 boleh dianggap sebagai kelas induk bagi ArrayLista87fdacec66f0909fc0757c19f2d2b1d

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 jenis Integer

List<? extends Number> list = new ArrayList<Integer>(); // correct
list.add(Integer.valueOf(1));  //error

Pertama, apabila memanggil kaedah tambah, E generik secara automatik menjadi a2b037db85f4e1df0e812b9647ac55a8

dan ralat dilaporkan pada baris kedua. Dengan kata lain, ? extends Number bukan kelas induk Integer. Di sini kita perlu membezakan bahawa Lista2b037db85f4e1df0e812b9647ac55a8 ialah kelas induk ArrayListc0f559cc8d56b43654fcbe4aa9df7b4a.

? 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 induk Integer

Ubah suai sedikit kod di atas dan ia akan betul:

List<? super Number> list = new ArrayList<Object>(); // correct
list.add(Integer.valueOf(1));  //correct

Pertama daripada semua, kerana penyongsangan, Listda50108ad159903fabe211f1543600e8 ialah Kelas induk ArrayLista87fdacec66f0909fc0757c19f2d2b1d, baris pertama adalah betul.

Baris kedua: ? super Number ialah kelas induk Integer, sebabnya ialah: ? super Number mewakili kelas induk Nombor tertentu, ia mungkin Serializable atau Object tetapi tidak kira yang mana satu , kelas induk Nombor mestilah kelas induk Integer, jadi baris kedua juga betul

Perlukah 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!

Kenyataan:
Artikel ini dikembalikan pada:yisu.com. Jika ada pelanggaran, sila hubungi admin@php.cn Padam