0Pricing
Java Academy · Pelajaran

Wildcard Berbatas Atas

? extends T untuk produsen.

Wildcard Berbatas Atas adalah pelajaran Java Academy gratis di CoddyKit. Ini adalah pelajaran 1 dari 4. Kamu bisa membaca pelajaran lengkapnya di bawah secara gratis — lalu praktikkan langsung di browser dengan editor kode bawaan dan tutor AI 24/7. Ini adalah bagian dari jalur belajar Java Academy, dan progresmu tersinkronisasi di web dan aplikasi CoddyKit. Kursus Java Academy mencakup 4 pelajaran total.

Generik Bersifat Invarian

Dalam Java, generik bersifat invarian. List<Integer> bukanlah List<Number>, meskipun tipe bilangan bulat merupakan tipe bilangan.

Hal ini mengejutkan pemula, tetapi menjaga sistem tipe tetap aman. Karakter pengganti melonggarkan batasan ini dengan aman.

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);
    }
}

Karakter Pengganti Berbatas Atas

? extends T adalah karakter pengganti berbatas atas. Artinya, "suatu tipe tidak dikenal yang merupakan T atau subtipe dari T".

List<? extends Number> dapat merujuk ke 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 dari Penyedia

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

Apa pun tipe elemen sebenarnya, elemen tersebut dijamin setidaknya bertipe bilangan, sehingga pembacaan aman secara tipe.

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 Dapat Menulis ke Dalamnya

Inilah batasannya: Anda tidak dapat menambahkan elemen ke dalam daftar ? extends Number (kecuali null).

Kompilator tidak mengetahui tipe elemen yang tepat. Daftar itu mungkin saja berupa List<Integer>, sehingga menambahkan Double akan tidak aman.

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());
    }
}

Mengapa Penulisan Dilarang

Bayangkan jika hal itu diperbolehkan. Anda dapat meneruskan List<Integer> sebagai List<? extends Number>, lalu menambahkan Double.

Kode berikutnya yang membaca daftar tersebut sebagai List<Integer> akan mendapatkan ClassCastException. Kompilator mencegah hal 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");
    }
}

Kasus Penggunaan Produsen

Gunakan ? extends T ketika suatu metode hanya menghasilkan (membaca) nilai untuk Anda.

Metode yang menyalin elemen dari koleksi sumber adalah contoh yang tepat.

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 Tipe Berbatas vs Karakter Pengganti

Jangan menyamakan <T extends Number> (sebuah parameter tipe berbatas) dengan ? extends Number (sebuah karakter pengganti).

  • Parameter tipe: menamai tipe agar dapat digunakan di seluruh metode.
  • Karakter pengganti: subtipe anonim yang tidak diketahui, digunakan ketika Anda tidak perlu menamainya.
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);
    }
}

Beberapa Batas

Parameter tipe dapat memiliki beberapa batas dengan &, seperti <T extends Number & Comparable<T>>.

Karakter pengganti hanya mendukung satu batas atas, jadi beberapa batas memerlukan parameter tipe yang diberi nama.

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)));
    }
}

Karakter Pengganti dengan Collections.max

JDK banyak menggunakan batas atas. Misalnya, untuk menjumlahkan atau menelusuri koleksi yang hanya dibaca.

Di sini kita mencari elemen terbesar dari daftar yang bertipe produsen.

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)));
    }
}

null Adalah Satu-satunya Nilai yang Dapat Ditulis

Satu-satunya hal yang dapat Anda tambahkan ke koleksi ? extends T adalah null, karena null dapat ditetapkan ke tipe referensi apa pun.

Hal ini jarang berguna, tetapi menjelaskan mengapa add tidak sepenuhnya dilarang, melainkan secara praktis tidak dapat digunakan.

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 Selalu Berhasil sebagai Object

Karena setiap tipe merupakan turunan dari Object, Anda selalu dapat membaca elemen dari daftar karakter pengganti apa pun sebagai Object.

Dengan batas atas Number, Anda mendapatkan keuntungan tambahan karena dapat langsung membacanya sebagai Number.

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());
    }
}

Pemeriksaan Singkat

Uji pemahaman Anda tentang batas atas.

Ringkasan

Anda telah mempelajari karakter pengganti berbatas atas:

  • ? extends T berarti subtipe T yang tidak diketahui.
  • Anda dapat membaca elemen sebagai T (sebuah produsen).
  • Anda tidak dapat menambahkan elemen yang bukan null.
  • Generik bersifat invarian, dan karakter pengganti melonggarkan aturan itu dengan aman.

Selanjutnya, kebalikannya: karakter pengganti berbatas 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));
    }
}

Pertanyaan yang Sering Diajukan

Apakah pelajaran “Wildcard Berbatas Atas” gratis?

Ya — teks lengkap “Wildcard Berbatas Atas” gratis dibaca di sini di web. Untuk praktiknya secara interaktif (editor kode bawaan dan tutor AI 24/7) dan buka sisa kursus Java Academy, upgrade ke CoddyKit PRO. Kursus Java Academy mencakup 4 pelajaran total.

Apa yang akan aku pelajari di “Wildcard Berbatas Atas”?

? extends T untuk produsen. Kamu berlatih Java Academy dengan kode praktik yang langsung kamu jalankan di browser, dan tutor AI 24/7 menjawab pertanyaanmu saat kamu mengerjakan pelajaran ini.

Apakah aku perlu pengalaman untuk memulai Java Academy?

Tidak diperlukan pengalaman sebelumnya. Java Academy di CoddyKit dirancang untuk pemula hingga pelajar tingkat lanjut, jadi kamu bisa memulai di sini atau dari awal dan belajar sesuai kecepatan kamu sendiri. Ini adalah pelajaran 1 dari 4.

Berapa lama pelajaran “Wildcard Berbatas Atas” memakan waktu?

Sebagian besar pelajaran CoddyKit memakan waktu sekitar 5–10 menit. Setiap pelajaran ringkas dan interaktif, jadi kamu membuat kemajuan stabil dan melanjutkan dari tempat kamu tinggalkan di web dan aplikasi.

Bisakah aku menulis dan menjalankan kode dalam pelajaran Java Academy ini?

Ya. Setiap pelajaran Java Academy menyertakan editor kode bawaan, jadi kamu menulis dan menjalankan kode nyata langsung di browser dan mendapatkan umpan balik AI instan — tidak diperlukan penyiapan lokal.

Semua pelajaran dalam kursus ini

  1. Wildcard Berbatas Atas
  2. Wildcard Berbatas Bawah
  3. Prinsip PECS
  4. Wildcard dalam API
← Kembali ke Java Academy