Rumah > Java > javaTutorial > Mengapa Senarai> Membenarkan Pelbagai Jenis Senarai Bersarang?

Mengapa Senarai> Membenarkan Pelbagai Jenis Senarai Bersarang?

Patricia Arquette
Lepaskan: 2024-11-18 21:38:02
asal
1030 orang telah melayarinya

Why Does a List<List<?>> Benarkan Pelbagai Jenis Senarai Bersarang? 
> Benarkan Pelbagai Jenis Senarai Bersarang? " />

Berbilang Kad Liar pada Kaedah Generik Boleh Mengelirukan Pengkompil Java

Masalahnya:

Menggunakan berbilang kad bebas pada kaedah generik boleh menyebabkan kekeliruan untuk pengkompil Java dan pengaturcara Pertimbangkan perkara berikut contoh:

public class TwoListsOfUnknowns {
    static void doNothing(List<?> list1, List<?> list2) {}

    public static void main(String[] args) {
        List<String> list1 = null;
        List<Integer> list2 = null;
        doNothing(list1, list2); // compiles fine!
    }
}
Salin selepas log masuk

Dua kad bebas yang tidak berkaitan boleh digunakan untuk memanggil doNothing dengan Senarai dan Senarai Walau bagaimanapun, variasi berikut tidak disusun:

public class TwoListsOfUnknowns2 {
    static void doSomethingIllegal(List<?> list1, List<?> list2) {
        list1.addAll(list2); 
            // DOES NOT COMPILE!!!
    }
}
Salin selepas log masuk

Tingkah laku ini dijangka kerana senarai1 dan senarai2 merujuk kepada jenis yang sama sekali berbeza.

Kekeliruan timbul dengan kod berikut:

public class LOLUnknowns1 {
    static void probablyIllegal(List<List<?>> lol, List<?> list) {
        lol.add(list); // this compiles!! how come???
    }
}
Salin selepas log masuk

Kod ini disusun, tetapi adakah mungkin untuk mempunyai Senarai> dan senarai kod diubah suai berikut tidak dikompil?

public class LOLUnknowns2 {
    static void rightfullyIllegal(
            List<List<? extends Number>> lol, List<?> list) {

        lol.add(list); // DOES NOT COMPILE! As expected!!!
    }
}
Salin selepas log masuk

Pengkompil nampaknya menjalankan tugasnya, tetapi kekeliruan berterusan dengan variasi berikut:

public class LOLUnknowns3 {
    static void probablyIllegalAgain(
            List<List<? extends Number>> lol, List<? extends Number> list) {

        lol.add(list); // compiles fine!!! how come???
    }
}
Salin selepas log masuk

Bukankah kod ini sepatutnya tidak dikompilkan kerana ia mungkin melibatkan Senarai> dan Senarai Untuk menjelaskan tingkah laku ini, mari mudahkan kod kembali kepada LOLUnknowns1 dan cuba invoke probablyIllegal:

Walaupun dengan jenis yang sama untuk kedua-dua kad bebas, kod itu tidak menyusun. Walau bagaimanapun, jenis nol untuk hujah pertama disusun:
public class LOLUnknowns1a {
    static void probablyIllegal(List<List<?>> lol, List<?> list) {
        lol.add(list); // this compiles!! how come???
    }

    public static void main(String[] args) {
        List<List<String>> lol = null;
        List<String> list = null;
        probablyIllegal(lol, list); // DOES NOT COMPILE!!
    }
}
Salin selepas log masuk

public class LOLUnknowns1b {
    static void probablyIllegal(List<List<?>> lol, List<?> list) {
        lol.add(list); // this compiles!! how come???
    }

    public static void main(String[] args) {
        List<String> list = null;
        probablyIllegal(null, list); // compiles fine!
    }
}
Salin selepas log masuk
Jawapannya:

Kekeliruan berpunca daripada salah faham tentang kad bebas bersarang, seperti List< ;Senarai>, sebenarnya bermaksud. Java Generics adalah invarian, bermakna hubungan antara jenis tidak berlaku untuk instantiasi generik. Ini terpakai pada senarai bersarang juga:

Oleh itu, Senarai> mewakili senarai yang unsur-unsurnya ialah senarai apa-apa jenis, bukan jenis yang sama secara khusus. Ini bermakna kod berikut adalah sah:
A List<String> is (captureable by) a List<?>.
A List<List<String>> is NOT (captureable by) a List<List<?>>.
A List<List<String>> IS (captureable by) a List<? extends List<?>>.
Salin selepas log masuk

List<List<?>> lolAny = new ArrayList<>();

lolAny.add(new ArrayList<Integer>());
lolAny.add(new ArrayList<String>());
Salin selepas log masuk
Secara ringkasan

Tingkah laku pengkompil Java dengan berbilang kad bebas generik ditentukan oleh peraturan penukaran tangkapan. Memahami had tangkapan kad bebas adalah penting untuk mengelakkan kekeliruan.

Atas ialah kandungan terperinci Mengapa Senarai> Membenarkan Pelbagai Jenis Senarai Bersarang?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

sumber:php.cn
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Artikel terbaru oleh pengarang
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan