JDK 7: Operator Berlian

Project Coin menyediakan banyak "peningkatan bahasa kecil" sebagai bagian dari fitur JDK 7 yang baru. Saya baru-baru ini membuat blog tentang pengalihan Koin Proyek pada Strings dan dalam posting ini saya menulis tentang Operator Berlian baru ( ).

Diamond Operator mengurangi beberapa verbositas Java seputar generik dengan memiliki tipe parameter compiler menyimpulkan untuk konstruktor kelas generik. Proposal asli untuk menambahkan Operator Berlian ke bahasa Java dibuat pada bulan Februari 2009 dan mencakup contoh sederhana ini:

Misalnya, pertimbangkan pernyataan tugas berikut:

Peta anagrams = HashMap baru ();

Ini agak panjang, jadi bisa diganti dengan ini:

Peta anagrams = new HashMap ();

Contoh di atas diberikan dalam proposal Jeremy Manson (yang merupakan salah satu yang pertama dalam menanggapi panggilan untuk ide Project Coin) sederhana, tetapi cukup menunjukkan bagaimana Diamond Operator diterapkan di JDK 7. Proposal Manson juga memberikan alasan yang signifikan mengapa penambahan ini diinginkan:

Persyaratan bahwa parameter tipe diduplikasi secara tidak perlu seperti

ini mendorong orang yang tidak beruntung

kelebihan metode pabrik statis, hanya karena jenis inferensi

bekerja pada pemanggilan metode.

Dengan kata lain, penambahan Koin Proyek JDK 7 dari Operator Berlian membawa inferensi tipe ke konstruktor yang telah tersedia dengan metode. Dengan metode jenis inferensi secara implisit dilakukan ketika seseorang meninggalkan spesifikasi jenis parameter eksplisit. Sebaliknya, dengan instantiation, operator berlian harus ditentukan secara eksplisit untuk "memberi tahu" compiler untuk menyimpulkan jenisnya.

Dalam proposal aslinya, Manson menunjukkan bahwa sintaks tanpa operator berlian khusus tidak dapat digunakan untuk menyimpulkan jenis untuk instansiasi secara implisit karena "untuk tujuan kompatibilitas mundur, Peta baru () menunjukkan jenis mentah, dan oleh karena itu tidak dapat digunakan untuk jenis kesimpulan." Halaman Jenis Inferensi dari Pelajaran Generik jejak Belajar Bahasa Java dari Tutorial Java menyertakan bagian yang disebut "Jenis Inferensi dan Instansiasi Kelas Generik" yang telah diperbarui untuk mencerminkan Java SE 7. Bagian ini juga menjelaskan mengapa khusus operator harus dispesifikasikan untuk secara eksplisit memberi tahu compiler untuk menggunakan inferensi tipe pada instansiasi:

Perhatikan bahwa untuk memanfaatkan inferensi tipe otomatis selama pembuatan instance kelas generik, Anda harus menentukan operator berlian. Dalam contoh berikut, kompilator menghasilkan peringatan konversi yang tidak dicentang karena konstruktor HashMap () mengacu pada tipe mentah HashMap, bukan Peta. Tipe

Dalam Item 24 ("Eliminate Unchecked Warnings") dari Effective Java Edisi Kedua, Josh Bloch menekankan dalam teks tebal , "Hilangkan setiap peringatan yang tidak dicentang semampu Anda." Bloch menunjukkan contoh peringatan konversi yang tidak dicentang yang terjadi ketika seseorang mengkompilasi kode yang menggunakan tipe mentah di sisi kanan deklarasi. Daftar kode berikutnya menunjukkan kode yang akan mengarah pada peringatan ini.

final Map
     
       statesToCities = new HashMap(); // raw! 
     

Dua cuplikan layar berikutnya menunjukkan tanggapan penyusun terhadap baris kode di atas. Gambar pertama menampilkan pesan saat tidak ada peringatan -Xlint yang diaktifkan dan yang kedua menampilkan peringatan yang lebih eksplisit yang terjadi saat -Xlint:uncheckeddiberikan sebagai argumen untuk javac.

Jika Java Efektif , Bloch menunjukkan bahwa peringatan khusus yang tidak dicentang ini mudah diatasi dengan secara eksplisit menyediakan tipe parameter untuk pembuatan instance kelas generik. Dengan JDK 7, ini akan menjadi lebih mudah! Daripada perlu menambahkan teks eksplisit dengan nama tipe ini, tipe bisa disimpulkan dalam banyak kasus dan spesifikasi operator berlian memberitahu compiler untuk membuat inferensi ini daripada menggunakan tipe mentah.

Daftar kode Java berikutnya memberikan contoh sederhana dari konsep ini. Ada metode yang mendemonstrasikan Instansiasi dari sebuah Set mentah, Instansiasi dari sebuah Set dengan spesifikasi eksplisit dari tipe parameternya, dan Instansiasi dari sebuah Set dengan tipe parameter yang disimpulkan karena spesifikasi dari operator berlian ( ).

package dustin.examples; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; import static java.lang.System.out; /** * Very simple demonstration of JDK 7's/Project Coin's "Diamond Operator." */ public class DiamondOperatorDemo { /** Use of "raw" type. */ private static Set rawWithoutExplicitTyping() { final Set names = new HashSet(); addNames(names); return names; } /** Explicitly specifying generic class's instantiation parameter type. */ private static Set explicitTypingExplicitlySpecified() { final Set names = new HashSet(); addNames(names); return names; } /** * Inferring generic class's instantiation parameter type with JDK 7's * 'Diamond Operator.' */ private static Set explicitTypingInferredWithDiamond() { final Set names = new HashSet(); addNames(names); return names; } private static void addNames(final Set namesToAddTo) { namesToAddTo.add("Dustin"); namesToAddTo.add("Rett"); namesToAddTo.add("Homer"); } /** * Main executable function. */ public static void main(final String[] arguments) { out.println(rawWithoutExplicitTyping()); out.println(explicitTypingExplicitlySpecified()); out.println(explicitTypingInferredWithDiamond()); } } 

Ketika kode di atas dikompilasi, hanya kasus "mentah" yang mengarah ke peringatan.

Pada titik ini, akan sangat berguna untuk melihat apa yang dikatakan javap tentang ketiga metode ini. Ini dilakukan dalam kasus ini dengan perintah ( -vopsi untuk verbose memberikan semua detail menarik dan -pmenampilkan detail menarik berikut untuk privatemetode):

javap -v -p -classpath classes dustin.examples.DiamondOperatorDemo 

Karena semua metode ini berada dalam satu kelas, ada satu aliran keluaran untuk seluruh kelas. Namun, untuk membuatnya lebih mudah untuk membandingkannya, saya telah memotong dan menempelkan hasilnya ke dalam format yang menyelaraskan keluaran javap untuk setiap metode satu sama lain. Setiap kolom mewakili javapkeluaran untuk salah satu metode. Saya telah mengubah warna font dari metode tertentu menjadi biru untuk membuatnya menonjol dan memberi label keluaran kolom itu.

Selain nama metode itu sendiri, tidak ada perbedaan dalam javapoutput. Ini karena penghapusan jenis umum Java berarti diferensiasi berdasarkan jenis tidak tersedia pada waktu proses. Tutorial Java tentang Generik menyertakan halaman bernama Type Erasure yang menjelaskan ini:

Kompilator menghapus semua informasi tentang argumen tipe aktual pada waktu kompilasi.

Jenis penghapusan ada sehingga kode baru dapat terus berinteraksi dengan kode lama. Menggunakan tipe mentah untuk alasan lain dianggap praktik pemrograman yang buruk dan harus dihindari bila memungkinkan.

Seperti yang diingatkan oleh kutipan di atas, erasure berarti bahwa untuk bytecode sebuah tipe mentah tidak berbeda dengan tipe parameter yang diketik secara eksplisit, tetapi juga mendorong pengembang untuk tidak menggunakan tipe mentah kecuali untuk mengintegrasikan dengan kode lama.

Kesimpulan

Dimasukkannya operator berlian ( ) di Java SE 7 berarti bahwa kode yang membuat instance kelas generik bisa kurang bertele-tele. Bahasa pengkodean secara umum, dan Java pada khususnya, bergerak menuju ide-ide seperti konvensi atas konfigurasi, konfigurasi dengan pengecualian, dan menyimpulkan hal-hal sesering mungkin daripada membutuhkan spesifikasi eksplisit. Bahasa yang diketik secara dinamis terkenal dengan inferensi tipe, tetapi bahkan Java yang diketik secara statis dapat melakukan lebih banyak daripada yang dilakukannya dan operator berlian adalah contohnya.

Posting asli tersedia di //marxsoftware.blogspot.com/

Artikel ini, "JDK 7: The Diamond Operator", awalnya diterbitkan oleh JavaWorld.