Operator berlian di java 7 memungkinkan kode seperti berikut:
List<String> list = new LinkedList<>();
Namun di Java 5/6, saya cukup menulis:
List<String> list = new LinkedList();
Pemahaman saya tentang penghapusan tipe adalah bahwa ini persis sama. (Lagi pula, generik akan dihapus saat runtime).
Kenapa repot-repot dengan berlian sama sekali? Apa fungsi / keamanan jenis baru yang dibolehkan? Jika tidak menghasilkan fungsionalitas baru mengapa mereka menyebutkannya sebagai fitur? Apakah pemahaman saya tentang konsep ini cacat?
java
generics
java-7
diamond-operator
tofarr
sumber
sumber
Jawaban:
Masalah dengan
adalah bahwa di sisi kiri, Anda menggunakan tipe generik di
List<String>
mana di sisi kanan Anda menggunakan tipe mentahLinkedList
. Jenis mentah di Jawa secara efektif hanya ada untuk kompatibilitas dengan kode pra-generik dan tidak boleh digunakan dalam kode baru kecuali Anda benar-benar harus melakukannya.Sekarang, jika Java memiliki generik dari awal dan tidak memiliki tipe, seperti
LinkedList
, yang awalnya dibuat sebelum generik, mungkin bisa membuatnya sehingga konstruktor untuk tipe generik secara otomatis menyimpulkan parameter tipenya dari kiri. Sisi-sisi penugasan jika memungkinkan. Tetapi tidak, dan itu harus memperlakukan tipe mentah dan tipe generik berbeda untuk kompatibilitas mundur. Itu membuat mereka perlu membuat cara yang sedikit berbeda , tetapi sama nyamannya, untuk mendeklarasikan instance baru dari objek generik tanpa harus mengulangi parameter tipenya ... operator berlian.Sejauh contoh asli Anda
List<String> list = new LinkedList()
, kompiler menghasilkan peringatan untuk tugas itu karena harus. Pertimbangkan ini:Generik ada untuk memberikan perlindungan waktu kompilasi terhadap melakukan hal yang salah. Dalam contoh di atas, menggunakan tipe mentah berarti Anda tidak mendapatkan perlindungan ini dan akan mendapatkan kesalahan saat runtime. Inilah sebabnya mengapa Anda tidak harus menggunakan jenis mentah.
Namun, operator intan memungkinkan sisi kanan penugasan untuk didefinisikan sebagai instance generik sebenarnya dengan parameter tipe yang sama dengan sisi kiri ... tanpa harus mengetikkan parameter itu lagi. Ini memungkinkan Anda untuk menjaga keamanan obat generik dengan upaya yang hampir sama dengan menggunakan jenis mentah.
Saya pikir hal utama yang perlu dipahami adalah bahwa jenis mentah (tanpa
<>
) tidak dapat diperlakukan sama dengan jenis generik. Ketika Anda mendeklarasikan tipe mentah, Anda tidak mendapatkan manfaat dan tipe pemeriksaan generik. Anda juga harus ingat bahwa obat generik adalah tujuan umum dari bahasa Jawa ... mereka tidak hanya berlaku untuk konstruktor no-arg dariCollection
s!sumber
-compatibility
saklar kompiler sedangkan jika tidak ada makajavac
akan melarang semua jenis mentah dan hanya menerapkan jenis generik saja? Ini akan membuat kode kita kurang verbose seperti itu.List<String> strings = new List<>()
tidak apa-apa, tetapi jika Anda mendefinisikanprivate List<String> my list;
, dan kemudian setengah jalan halaman Anda instantiatemy_list = new List<>()
, maka itu tidak keren! Apa isi daftar saya lagi? Oh, biarkan aku mencari-cari definisi. Tiba-tiba, manfaat dari jalan pintas berlian berlalu.my_list = getTheList()
? Ada beberapa cara yang lebih baik bagaimana menangani masalah seperti ini: 1. gunakan IDE yang menunjukkan kepada Anda jenis variabel saat mouse di-arahkan. 2. menggunakan nama-nama variabel yang lebih bermakna, sepertiprivate List<String> strings
3. jangan memecah deklarasi dan inisialisasi variabel kecuali Anda benar-benar harus.Pemahaman Anda sedikit cacat. Operator berlian adalah fitur yang bagus karena Anda tidak perlu mengulangi sendiri. Masuk akal untuk menentukan jenis sekali ketika Anda mendeklarasikan jenis tetapi hanya tidak masuk akal untuk mendefinisikannya lagi di sisi kanan. Prinsip KERING.
Sekarang untuk menjelaskan semua fuzz tentang mendefinisikan tipe. Anda benar bahwa jenis dihapus pada saat runtime tetapi begitu Anda ingin mengambil sesuatu dari Daftar dengan definisi jenis Anda mendapatkannya kembali sebagai jenis yang telah Anda tetapkan saat mendeklarasikan daftar itu jika tidak maka akan kehilangan semua fitur tertentu dan hanya memiliki Fitur objek kecuali ketika Anda akan melemparkan objek yang diambil ke tipe aslinya yang kadang-kadang bisa sangat rumit dan menghasilkan ClassCastException.
Menggunakan
List<String> list = new LinkedList()
akan memberi Anda peringatan mentah.sumber
List<String> list = new LinkedList()
adalah kode yang benar. Anda tahu ini dan saya juga tahu ini. Dan pertanyaannya (seperti yang saya mengerti) adalah: mengapa hanya java compiler yang tidak mengerti bahwa kode ini cukup aman?List<String> list = new LinkedList()
adalah tidak kode yang benar. Tentu, alangkah baiknya jika itu! Dan mungkin bisa saja jika Java memiliki obat generik sejak awal dan tidak harus berurusan dengan kompatibilitas mundur dari jenis generik yang dulunya non-generik, tetapi memang demikian.<?>
jika berinteraksi dengan kode lawas) dan operator berlian yang tidak berguna seharusnya tidak ada.Baris ini menyebabkan peringatan [tidak dicentang]:
Jadi, pertanyaannya mengubah: mengapa peringatan [tidak dicentang] tidak ditekan secara otomatis hanya untuk kasus ketika koleksi baru dibuat?
Saya pikir, itu akan menjadi tugas yang jauh lebih sulit daripada menambahkan
<>
fitur.UPD : Saya juga berpikir bahwa akan ada kekacauan jika secara legal menggunakan tipe mentah 'hanya untuk beberapa hal'.
sumber
Secara teori, operator intan memungkinkan Anda untuk menulis kode yang lebih ringkas (dan dapat dibaca) dengan menyimpan argumen tipe berulang. Dalam praktiknya, itu hanya dua karakter membingungkan yang lebih memberi Anda apa-apa. Mengapa?
IMHO, memiliki cara yang jelas dan sederhana untuk menandai sumber sebagai Java 7 akan lebih berguna daripada menciptakan hal-hal aneh seperti itu. Dalam kode yang ditandai, jenis mentah dapat dilarang tanpa kehilangan apa pun.
Btw., Saya tidak berpikir bahwa itu harus dilakukan menggunakan kompilasi switch. Versi Java dari file program adalah atribut dari file tersebut, tidak ada opsi sama sekali. Menggunakan sesuatu yang sepele
dapat memperjelas (Anda dapat memilih sesuatu yang lebih canggih termasuk satu atau lebih kata kunci mewah). Itu bahkan akan memungkinkan untuk mengkompilasi sumber yang ditulis untuk versi Java yang berbeda bersama-sama tanpa masalah. Ini akan memungkinkan pengenalan kata kunci baru (misalnya, "modul") atau menjatuhkan beberapa fitur usang (beberapa kelas non-publik non-bersarang dalam satu file atau apa pun) tanpa kehilangan kompatibilitas apa pun.
sumber
new ArrayList(anotherList)
dannew ArrayList<>(anotherList)
(terutama jika sedang ditugaskanList<String>
dananotherList
aList<Integer>
)?new @RawType List()
. Itu sudah sintaks Java 8 yang valid dan ketik anotasi memungkinkan untuk menggunakannya di setiap tempat di mana diperlukan, misalnya@RawType List = (@RawType List) genericMethod();
. Menimbang bahwa tipe mentah saat ini membuat peringatan kompiler kecuali jika@SuppressWarnings
telah ditempatkan,@RawType
akan menjadi pengganti yang wajar dan sintaksis yang lebih halus tidak diperlukan.Saat Anda menulis
List<String> list = new LinkedList();
, kompiler menghasilkan peringatan "tidak dicentang". Anda mungkin mengabaikannya, tetapi jika Anda mengabaikan peringatan ini, Anda mungkin juga kehilangan peringatan yang memberi tahu Anda tentang masalah keamanan tipe nyata.Jadi, lebih baik menulis kode yang tidak menghasilkan peringatan tambahan, dan operator berlian memungkinkan Anda melakukannya dengan mudah tanpa pengulangan yang tidak perlu.
sumber
Semua yang dikatakan dalam respons lain valid tetapi kasus penggunaan tidak sepenuhnya IMHO valid. Jika seseorang memeriksa Guava dan terutama koleksi hal-hal terkait, hal yang sama telah dilakukan dengan metode statis. Misalnya Lists.newArrayList () yang memungkinkan Anda untuk menulis
atau dengan impor statis
Guava memiliki fitur-fitur lain yang sangat kuat seperti ini dan saya sebenarnya tidak bisa memikirkan banyak kegunaan untuk <>.
Akan lebih bermanfaat jika mereka menggunakan default perilaku operator berlian, yaitu, tipe disimpulkan dari sisi kiri ekspresi atau jika tipe sisi kiri disimpulkan dari sisi kanan. Yang terakhir inilah yang terjadi di Scala.
sumber
Intinya bagi operator intan adalah untuk mengurangi mengetik kode ketika mendeklarasikan tipe generik. Itu tidak memiliki efek pada runtime sama sekali.
Satu-satunya perbedaan jika Anda menentukan di Java 5 dan 6,
adalah bahwa Anda harus menentukan
@SuppressWarnings("unchecked")
kelist
(jika tidak, Anda akan mendapatkan peringatan pemain yang tidak dicentang). Pemahaman saya adalah bahwa operator berlian berusaha membuat pengembangan lebih mudah. Itu tidak ada hubungannya dengan eksekusi runtime generik sama sekali.sumber