Apa arti tanda tanya dalam parameter tipe Java generics?


216

Ini adalah potongan kecil kode yang diambil dari beberapa contoh yang menyertai Stanford Parser. Saya telah mengembangkan di Jawa selama sekitar 4 tahun, tetapi tidak pernah memiliki pemahaman yang sangat kuat tentang apa yang seharusnya ditunjukkan oleh gaya kode ini.

List<? extends HasWord> wordList = toke.tokenize();

Saya tidak khawatir tentang detail kode. Yang saya bingung adalah apa yang seharusnya disampaikan oleh ekspresi generik, dalam bahasa Inggris.

Adakah yang bisa menjelaskan hal ini kepada saya?


Jawaban:


226
? extends HasWord

berarti "Kelas / antarmuka yang memanjang HasWord." Dengan kata lain, HasWorditu sendiri atau salah satu dari anak-anaknya ... pada dasarnya apa pun yang sesuai dengan instanceof HasWordplus null.

Dalam istilah yang lebih teknis, ? extends HasWordadalah wildcard terbatas, tercakup dalam Item 31 dari Java Edisi 3 Efektif , mulai dari halaman 139. Bab yang sama dari Edisi 2 tersedia online dalam bentuk PDF ; bagian pada wildcard terbatas adalah Item 28 mulai dari halaman 134.

Pembaruan: Tautan PDF telah diperbarui sejak Oracle menghapusnya beberapa waktu lalu. Sekarang menunjuk ke salinan yang dipandu oleh Sekolah Teknik Elektronika dan Ilmu Komputer Queen Mary University London.

Pembaruan 2: Mari kita sedikit lebih detail tentang mengapa Anda ingin menggunakan wildcard.

Jika Anda mendeklarasikan metode yang tanda tangannya ingin Anda lewati List<HasWord>, maka satu-satunya hal yang dapat Anda lewati adalah a List<HasWord>.

Namun, jika tanda tangan itu List<? extends HasWord>maka Anda bisa lewat List<ChildOfHasWord>.

Perhatikan bahwa ada perbedaan tipis antara List<? extends HasWord>dan List<? super HasWord>. Seperti yang dikatakan Joshua Bloch: PECS = produsen-meluas, konsumen-super.

Apa artinya ini adalah bahwa jika Anda meneruskan koleksi yang metode Anda tarik data dari (yaitu koleksi menghasilkan elemen untuk metode Anda untuk menggunakan), Anda harus menggunakan extends. Jika Anda meneruskan koleksi yang ditambahkan metode Anda ke data (mis. Koleksi tersebut menggunakan elemen yang dibuat metode Anda), itu harus digunakan super.

Ini mungkin terdengar membingungkan. Namun, Anda dapat melihatnya di List's sortperintah (yang hanya jalan pintas untuk versi dua-arg dari Collections.sort). Alih-alih mengambil Comparator<T>, itu sebenarnya membutuhkan Comparator<? super T>. Dalam hal ini, Pembanding mengkonsumsi elemen-elemen Listuntuk menyusun ulang Daftar itu sendiri.


17
"apa pun yang akan bekerja dengan instanceof" - ditambah nilai nol. Ingat bahwa nilai nol mengembalikan false untuk setiap contoh pemeriksaan.
Eyal Schneider

12
Jangan lupa antarmuka. Itu? tidak harus mewakili kelas!
Mark Peters

9
List<HasWord>persis seperti yang Anda gambarkan: Daftar yang berisi objek apa pun xyang x instanceof HasWordmengembalikan true, dan null. Anda tidak perlu wildcard untuk ini. Wildcard berarti bahwa itu sebenarnya bisa menjadi daftar tipe lain juga, asalkan tipe ini adalah subtipe dari HasWord. (Maaf atas komentar terakhir.)
Paŭlo Ebermann

1
Tautan PDF tampaknya tidak berfungsi, tetapi ini berguna bagi saya: docs.oracle.com/javase/tutorial/extra/generics/wildcards.html
user1338062

Aneh, saya tidak pernah mendapat pesan tahun lalu ketika @ user1338062 memposting dan tidak tahu tautan PDF tidak berfungsi. Diperbaiki sekarang Saya juga menambahkan tautan ke buku itu sendiri.
Powerlord

65

Tanda tanya adalah penanda untuk 'jenis apa pun'. ?sendiri artinya

Jenis apa pun yang diperpanjang Object(termasuk Object)

sedangkan contoh Anda di atas berarti

Jenis apa pun yang memperluas atau mengimplementasikan HasWord(termasuk HasWordjika HasWordkelas non-abstrak)


2
jadi apa public Set<Class<?>> getClasses()artinya? Apa bedanya dengan Set<Class>? Saya sedang melihat javax.ws.rs.core.Application.
brankas

14

List<? extends HasWord>menerima setiap kelas konkret yang memperluas HasWord. Jika Anda memiliki kelas berikut ...

public class A extends HasWord { .. }
public class B extends HasWord { .. }
public class C { .. }
public class D extends SomeOtherWord { .. }

... wordListHANYA bisa berisi daftar As atau B atau campuran keduanya karena kedua kelas memperpanjang induk yang sama atau null(yang gagal contoh pemeriksaan HasWorld).


8
Tidak hanya konkret, juga subkelas abstrak.
bloparod

2
Tidak hanya beton dan subclass abstrak, tetapi juga sub-interface: List<? extends Collection<String>> list = new ArrayList<List<String>>();.
Mark Peters

2
Anda tidak perlu wildcard untuk ini, sebenarnya: List<HasWord>melakukan dengan baik untuk ini. Intinya di sini adalah bahwa variabel ini dapat berisi List<A>atau List<B>juga a List<HasWord>.
Paŭlo Ebermann

12

Mungkin contoh "dunia nyata" yang dibuat-buat akan membantu.

Di tempat kerja saya, kami memiliki tempat sampah yang berbeda rasa. Semua tempat sampah mengandung sampah, tetapi beberapa tempat sampah adalah spesialis dan tidak mengambil semua jenis sampah. Jadi kita punya Bin<CupRubbish>dan Bin<RecylcableRubbish>. Sistem tipe perlu memastikan saya tidak dapat memasukkan saya HalfEatenSandwichRubbishke salah satu dari jenis ini, tetapi dapat masuk ke tempat sampah umum Bin<Rubbish>. Jika saya ingin berbicara tentang Bindari Rubbishyang mungkin khusus jadi saya tidak bisa dimasukkan ke dalam sampah tidak sesuai, maka itu akan menjadi Bin<? extends Rubbish>.

(Catatan: ? extendstidak berarti hanya baca. Misalnya, saya dapat dengan tindakan pencegahan yang tepat mengeluarkan sepotong sampah dari tempat khusus yang tidak diketahui dan kemudian meletakkannya kembali di tempat yang berbeda.)

Tidak yakin berapa banyak yang membantu. Pointer-to-pointer di hadapan polimorfisme tidak sepenuhnya jelas.


5

Dalam Bahasa Inggris:

Itu Listdari beberapa tipe yang memperluas kelas HasWord, termasukHasWord

Secara umum ?dalam generik berarti kelas apa saja. Dan extends SomeClassmenentukan bahwa objek itu harus diperluas SomeClass(atau kelas itu).


1
Sebenarnya, ketik bukan kelas . Ini berfungsi dengan baik untuk antarmuka.
Paŭlo Ebermann

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.