Java Academy · Pelajaran

Kad Liar Berhad Atas

? extends T untuk pengeluar

Pelajaran 1 daripada 413 langkah

Kad Liar Berhad Atas ialah pelajaran Java Academy percuma di CoddyKit. Ini ialah pelajaran 1 daripada 4. Anda boleh membaca keseluruhan pelajaran di bawah secara percuma — kemudian berlatih secara praktikal dalam pelayar menggunakan penyunting kod terbina dalam dan tutor kecerdasan buatan 24/7. Pelajaran ini merupakan sebahagian daripada laluan pembelajaran Java Academy, dan kemajuan anda disegerakkan merentas web serta aplikasi CoddyKit. Kursus Java Academy merangkumi sejumlah 4 pelajaran.

Generik Tidak Kovarian

Dalam Java, generik adalah invarian. List<Integer> bukan List<Number>, walaupun integer ialah nombor.

Hal ini mengejutkan pelajar baharu, tetapi ia memastikan sistem jenis kekal mantap. Kad bebas melonggarkan sekatan ini dengan selamat.

import java.util.List;

public class Main {
    public static void main(String[] args) {
        List<Integer> ints = List.of(1, 2, 3);
        // List<Number> nums = ints; // would NOT compile
        System.out.println("List<Integer> is not List<Number>");
        System.out.println(ints);
    }
}

Kad Bebas Berhad Atas

? extends T ialah kad bebas berhad atas. Ia bermaksud suatu jenis tidak diketahui yang sama dengan T atau subjenis T.

List<? extends Number> boleh merujuk kepada List<Integer>, List<Double> atau List<Number>.

import java.util.List;

public class Main {
    public static void main(String[] args) {
        List<? extends Number> a = List.of(1, 2, 3);
        List<? extends Number> b = List.of(1.5, 2.5);
        System.out.println(a.get(0));
        System.out.println(b.get(0));
    }
}

Membaca daripada Pengeluar

Dengan ? extends Number, Anda boleh membaca elemen sebagai Number.

Walau apa pun jenis elemen sebenar, ia dijamin sekurang-kurangnya daripada jenis nombor, jadi pembacaan adalah selamat dari segi jenis.

import java.util.List;

public class Main {
    static double sum(List<? extends Number> list) {
        double total = 0;
        for (Number n : list) total += n.doubleValue();
        return total;
    }
    public static void main(String[] args) {
        System.out.println(sum(List.of(1, 2, 3)));
        System.out.println(sum(List.of(1.5, 2.5)));
    }
}

Anda Tidak Boleh Menulis Padanya

Perhatikan perkara penting ini: anda tidak boleh menambah elemen pada senarai ? extends Number (kecuali null).

Pengkompil tidak mengetahui jenis elemen yang tepat. Senarai itu mungkin berupa List<Integer>, jadi menambah nilai perpuluhan akan menjadi tidak selamat.

import java.util.ArrayList;
import java.util.List;

public class Main {
    public static void main(String[] args) {
        List<? extends Number> list = new ArrayList<Integer>();
        // list.add(1);   // does NOT compile
        // list.add(1.5); // does NOT compile
        System.out.println("Cannot add to ? extends Number");
        System.out.println("size = " + list.size());
    }
}

Sebab Penulisan Dilarang

Bayangkan jika perkara itu dibenarkan. Anda boleh menghantar List<Integer> sebagai List<? extends Number> dan kemudian menambah nilai perpuluhan.

Kod yang membaca senarai itu kemudian sebagai List<Integer> akan menerima ClassCastException. Pengkompil menghalang perkara ini dengan melarang penulisan.

import java.util.List;

public class Main {
    public static void main(String[] args) {
        // Conceptual: this is why add is blocked
        System.out.println("Writing a Double into a List<Integer> would corrupt it");
        System.out.println("so ? extends bans all adds");
    }
}

Kes Penggunaan Pengeluar

Gunakan ? extends T apabila kaedah hanya menghasilkan (membaca keluar) nilai untuk anda.

Kaedah yang menyalin elemen keluar daripada koleksi sumber ialah contoh yang sempurna.

import java.util.ArrayList;
import java.util.List;

public class Main {
    static List<Number> copyOut(List<? extends Number> source) {
        List<Number> dest = new ArrayList<>();
        for (Number n : source) dest.add(n);
        return dest;
    }
    public static void main(String[] args) {
        System.out.println(copyOut(List.of(1, 2, 3)));
    }
}

Parameter Jenis Bersempadan berbanding Kad Bebas

Jangan keliru antara <T extends Number> (sebuah parameter jenis bersempadan) dengan ? extends Number (sebuah kad bebas).

  • Parameter jenis: menamakan jenis untuk digunakan merentasi kaedah.
  • Kad bebas: subjenis tanpa nama yang tidak diketahui, digunakan apabila anda tidak perlu menamakannya.
import java.util.List;

public class Main {
    static <T extends Number> T first(List<T> list) { return list.get(0); }
    public static void main(String[] args) {
        Integer i = first(List.of(10, 20));
        System.out.println(i);
    }
}

Berbilang Sempadan

Parameter jenis boleh mempunyai berbilang sempadan menggunakan &, seperti <T extends Number & Comparable<T>>.

Kad bebas hanya menyokong satu sempadan atas, jadi berbilang sempadan memerlukan parameter jenis yang dinamakan.

import java.util.List;

public class Main {
    static <T extends Number & Comparable<T>> T max(List<T> list) {
        T best = list.get(0);
        for (T t : list) if (t.compareTo(best) > 0) best = t;
        return best;
    }
    public static void main(String[] args) {
        System.out.println(max(List.of(3, 9, 1, 7)));
    }
}

Kad Bebas dengan Collections.max

JDK menggunakan sempadan atas secara meluas, contohnya untuk menjumlahkan atau mengimbas koleksi baca sahaja.

Di sini kita mencari nilai terbesar dalam senarai yang ditaip sebagai pengeluar.

import java.util.List;

public class Main {
    static double largest(List<? extends Number> nums) {
        double max = Double.NEGATIVE_INFINITY;
        for (Number n : nums) max = Math.max(max, n.doubleValue());
        return max;
    }
    public static void main(String[] args) {
        System.out.println(largest(List.of(4, 2, 9, 1)));
        System.out.println(largest(List.of(0.5, 9.9, 3.3)));
    }
}

Nilai Kosong Sahaja Boleh Ditulis

Satu-satunya perkara yang boleh anda tambah pada koleksi ? extends T ialah null, kerana nilai kosong boleh diberikan kepada mana-mana jenis rujukan.

Perkara ini jarang berguna, tetapi menerangkan sebab add tidak dilarang sepenuhnya, sebaliknya hanya secara praktikal.

import java.util.ArrayList;
import java.util.List;

public class Main {
    public static void main(String[] args) {
        List<? extends Number> list = new ArrayList<Number>();
        // Only null is assignable; demonstrated conceptually
        System.out.println("Only null could be added; we avoid that");
        System.out.println("size = " + list.size());
    }
}

Membaca Keluar sebagai Objek Sentiasa Berfungsi

Oleh sebab setiap jenis ialah subjenis Objek, anda sentiasa boleh membaca elemen daripada mana-mana senarai kad bebas sebagai Object.

Dengan sempadan atas nombor, anda mendapat kelebihan membaca elemen itu terus sebagai nombor.

import java.util.List;

public class Main {
    public static void main(String[] args) {
        List<? extends Number> nums = List.of(1, 2.0, 3L);
        for (Object o : nums) System.out.println(o.getClass().getSimpleName());
    }
}

Semakan Pantas

Uji pemahaman anda tentang sempadan atas.

Rumusan

Anda telah mempelajari kad bebas bersempadan atas:

  • ? extends T bermaksud subjenis T yang tidak diketahui.
  • Anda boleh membaca elemen sebagai T (sebuah pengeluar).
  • Anda tidak boleh menambah elemen bukan kosong.
  • Generik adalah tidak invarian, dan kad bebas melonggarkan peraturan itu dengan selamat.

Seterusnya, imej cerminnya: kad bebas bersempadan bawah.

import java.util.List;

public class Main {
    public static void main(String[] args) {
        List<? extends Number> nums = List.of(1, 2, 3);
        System.out.println("Upper bound recap: read " + nums.get(0));
    }
}
Percuma untuk bermula

Pelajari Java dengan tutor kecerdasan buatan — percuma

Tulis dan jalankan kod sebenar dalam pelayar anda, dapatkan bantuan segera daripada tutor kecerdasan buatan yang tersedia 24/7, dan sambung semula dari tempat anda berhenti di web atau dalam aplikasi.

Kursus
104
Pelajaran
374

Soalan Lazim

Adakah pelajaran “Kad Liar Berhad Atas” percuma?

Ya — teks penuh “Kad Liar Berhad Atas” boleh dibaca secara percuma di web ini. Untuk berlatih secara interaktif menggunakan penyunting kod terbina dalam dan tutor kecerdasan buatan 24/7, serta membuka kunci baki kursus Java Academy, tingkat taraf kepada CoddyKit PRO. Kursus Java Academy merangkumi sejumlah 4 pelajaran.

Apakah yang akan saya pelajari dalam “Kad Liar Berhad Atas”?

? extends T untuk pengeluar Anda berlatih Java Academy menggunakan kod praktikal yang dijalankan terus dalam pelayar, manakala tutor kecerdasan buatan 24/7 menjawab soalan anda semasa anda mengikuti pelajaran.

Adakah saya memerlukan pengalaman untuk memulakan Java Academy?

Tiada pengalaman terdahulu diperlukan. Pembelajaran Java Academy di CoddyKit disusun untuk pelajar daripada peringkat pemula hingga lanjutan, jadi anda boleh bermula di sini atau dari awal dan belajar mengikut kadar anda sendiri. Ini ialah pelajaran 1 daripada 4.

Berapa lamakah pelajaran “Kad Liar Berhad Atas” diambil?

Kebanyakan pelajaran CoddyKit mengambil masa kira-kira 5–10 minit. Setiap pelajaran ringkas dan interaktif, jadi anda boleh membuat kemajuan secara berterusan dan menyambung tepat dari tempat anda berhenti di web atau aplikasi.

Bolehkah saya menulis dan menjalankan kod dalam pelajaran Java Academy ini?

Ya. Setiap pelajaran Java Academy menyertakan penyunting kod terbina dalam, jadi anda boleh menulis dan menjalankan kod sebenar terus dalam pelayar serta menerima maklum balas kecerdasan buatan serta-merta — tanpa memerlukan persediaan setempat.

Semua pelajaran dalam kursus ini

  1. Kad Liar Berhad Atas
  2. Kad Liar Berhad Bawah
  3. Prinsip PECS
  4. Kad Liar dalam API
← Kembali ke Java Academy