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

Mengapa Senarai> Membenarkan Pelbagai Jenis Senarai Bersarang?

Patricia Arquette
Patricia Arquetteasal
2024-11-18 21:38:021016semak imbas

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

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

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???
    }
}

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

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???
    }
}

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

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!
    }
}
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<?>>.

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

lolAny.add(new ArrayList<Integer>());
lolAny.add(new ArrayList<String>());
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!

Kenyataan:
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