Saya punya beberapa pertanyaan tentang wildcard generik di Java:
Apa perbedaan antara
List<? extends T>
danList<? super T>
?Apa itu wildcard terbatas dan apa itu wildcard tak terbatas?
Saya punya beberapa pertanyaan tentang wildcard generik di Java:
Apa perbedaan antara List<? extends T>
dan List<? super T>
?
Apa itu wildcard terbatas dan apa itu wildcard tak terbatas?
Jawaban:
Di pertanyaan pertama Anda, <? extends T>
dan <? super T>
merupakan contoh karakter pengganti berbatas. Karakter pengganti tak terbatas terlihat seperti <?>
, dan pada dasarnya berarti <? extends Object>
. Ini secara longgar berarti generik dapat jenis apa saja. Karakter pengganti yang dibatasi ( <? extends T>
atau <? super T>
) menempatkan batasan pada tipe dengan mengatakan bahwa itu harus memperluas tipe tertentu ( <? extends T>
dikenal sebagai batas atas), atau harus merupakan leluhur dari tipe tertentu ( <? super T>
dikenal sebagai batas bawah) .
Tutorial Java memiliki beberapa penjelasan generik yang cukup bagus di artikel Wildcard dan More Fun with Wildcard .
<? super C>
berarti tipe Anda dibatasi untuk sesuatu C
di atas dalam hierarki tipe. (Maaf atas balasan yang sangat terlambat. Saya kira kami tidak memiliki pemberitahuan komentar 2 tahun yang lalu?)
Jika Anda memiliki hierarki kelas A, B adalah subkelas A, dan C dan D keduanya adalah subkelas B seperti di bawah ini
class A {}
class B extends A {}
class C extends B {}
class D extends B {}
Kemudian
List<? extends A> la;
la = new ArrayList<B>();
la = new ArrayList<C>();
la = new ArrayList<D>();
List<? super B> lb;
lb = new ArrayList<A>(); //fine
lb = new ArrayList<C>(); //will not compile
public void someMethod(List<? extends B> lb) {
B b = lb.get(0); // is fine
lb.add(new C()); //will not compile as we do not know the type of the list, only that it is bounded above by B
}
public void otherMethod(List<? super B> lb) {
B b = lb.get(0); // will not compile as we do not know whether the list is of type B, it may be a List<A> and only contain instances of A
lb.add(new B()); // is fine, as we know that it will be a super type of A
}
Karakter pengganti terikat seperti di ? extends B
mana B adalah tipe tertentu. Artinya, jenisnya tidak diketahui tetapi "terikat" dapat ditempatkan di atasnya. Dalam hal ini, itu dibatasi oleh beberapa kelas, yang merupakan subkelas dari B.
List<? super B>
menggambarkan sebagai Daftar menerima tipe yang merupakan kelas induk dari kelas B ? Itulah mengapa C dan D tidak dapat dikompilasi hmm?
Josh Bloch juga memiliki penjelasan yang baik tentang kapan harus menggunakan super
dan extends
dalam obrolan video google io ini di mana dia menyebutkan mnemonic Produsen extends
Konsumensuper
.
Dari slide presentasi:
Misalkan Anda ingin menambahkan metode massal ke
Stack<E>
void pushAll(Collection<? extends E> src);
- src adalah produser E.
void popAll(Collection<? super E> dst);
- dst adalah konsumen E.
Ada kalanya Anda ingin membatasi jenis jenis yang diizinkan untuk diteruskan ke parameter jenis. Misalnya, metode yang beroperasi pada angka mungkin hanya ingin menerima instance Number atau subclassnya. Untuk inilah parameter tipe terikat.
Collection<? extends MyObject>
berarti ia dapat menerima semua objek yang memiliki hubungan IS- A dengan MyObject (yaitu objek apa pun yang merupakan tipe myObject atau kita dapat mengatakan objek apa pun dari subkelas MyObject) atau objek kelas MyObject.
Sebagai contoh:
class MyObject {}
class YourObject extends MyObject{}
class OurObject extends MyObject{}
Kemudian,
Collection<? extends MyObject> myObject;
hanya akan menerima MyObject atau anak-anak dari MyObject (yaitu setiap objek bertipe OurObject atau YourObject atau MyObject, tetapi bukan objek superclass dari MyObject).
Secara umum,
Jika suatu struktur mengandung elemen dengan tipe bentuk
? extends E
, kita dapat mengeluarkan elemen dari struktur, tetapi kita tidak dapat memasukkan elemen ke dalam struktur
List<Integer> ints = new ArrayList<Integer>();
ints.add(1);
ints.add(2);
List<? extends Number> nums = ints;
nums.add(3.14); // compile-time error
assert ints.toString().equals("[1, 2, 3.14]");
Untuk memasukkan elemen ke dalam struktur, kita membutuhkan jenis karakter pengganti lain yang disebut Wildcards with super
,
List<Object> objs = Arrays.<Object>asList(2, 3.14, "four");
List<Integer> ints = Arrays.asList(5, 6);
Collections.copy(objs, ints);
assert objs.toString().equals("[5, 6, four]");
public static <T> void copy(List<? super T> dst, List<? extends T> src) {
for (int i = 0; i < src.size(); i++) {
dst.set(i, src.get(i));
}
}
Karakter pengganti umum dibuat untuk membuat metode yang beroperasi di Koleksi lebih dapat digunakan kembali.
Misalnya, jika suatu metode memiliki parameter List<A>
, kita hanya dapat memberikannya List<A>
kepada metode ini. Ini adalah pemborosan untuk fungsi metode ini dalam beberapa keadaan :
List<A>
, maka kita harus diizinkan untuk memberikan List<A-sub>
metode ini. (Karena A-sub ADALAH A)List<A>
, maka kita harus diizinkan untuk memberikan List<A-super>
ke metode ini. (Karena A ADALAH A-super)