Ini adalah versi sederhana dari kode yang dipermasalahkan, satu kelas generik menggunakan kelas lain dengan parameter tipe generik dan perlu meneruskan salah satu tipe generik ke metode dengan parameter varargs:
class Assembler<X, Y> {
void assemble(X container, Y... args) { ... }
}
class Component<T> {
void useAssembler(T something) {
Assembler<String, T> assembler = new Assembler<String, T>();
//generates warning:
// Type safety : A generic array of T is
// created for a varargs parameter
assembler.assemble("hello", something);
}
}
Apakah ada cara yang benar untuk meneruskan parameter generik ke metode varargs tanpa menemui peringatan ini?
Tentu saja seperti itu
assembler.assemble("hello", new T[] { something });
tidak berfungsi karena Anda tidak dapat membuat array generik.
Jawaban:
Selain menambahkan
@SuppressWarnings("unchecked")
, saya rasa tidak.Laporan bug ini memiliki lebih banyak informasi tetapi bermuara pada kompiler yang tidak menyukai array tipe generik.
sumber
Tom Hawtin menunjukkan ini dalam komentar, tetapi untuk lebih eksplisit: ya, Anda dapat menyelesaikan ini di situs deklarasi (daripada situs panggilan (berpotensi banyak)): beralih ke JDK7.
Seperti yang dapat Anda lihat di posting blog Joseph Darcy , latihan Project Coin untuk memilih beberapa peningkatan bahasa tambahan kecil untuk Java 7 menerima proposal Bob Lee untuk memungkinkan sesuatu seperti
@SuppressWarnings("varargs")
di sisi metode untuk membuat peringatan ini hilang dalam situasi di mana ia dikenal sebagai aman.Ini telah diterapkan di OpenJDK dengan komit ini .
Ini mungkin atau mungkin tidak berguna untuk proyek Anda (banyak orang tidak akan senang beralih ke versi JVM pra-rilis yang tidak stabil!) Tetapi mungkin itu - atau mungkin seseorang yang menemukan pertanyaan ini nanti (setelah JDK7 keluar ) akan bermanfaat.
sumber
Jika Anda mencari antarmuka tipe fasih, Anda bisa mencoba pola builder. Tidak sesingkat varargs tetapi jenisnya aman.
Metode statis yang diketik secara umum dapat menghilangkan beberapa pelat ketel saat menggunakan pembangun, sembari tetap mempertahankan keamanan jenisnya.
Pembangun
Menggunakannya
sumber
Collection
(dalam hal ini aArrayList
) dipaksakan kepada penelepon, sedangkan mereka mungkin tahu bahwa aLinkedList
lebih tepat, atau array yang tidak dapat diubah itu sendiri (seperti varargs dari pertanyaan OP). Dalam kasus penggunaan khusus, ini mungkin tepat, tetapi hanya menunjukkan bahwa ini juga merupakan batasan, dengan cara, tergantung pada kode di sekitar ini dan kebutuhan Anda.Pengecoran parameter secara eksplisit ke Object dalam pemanggilan metode vararg akan membuat kompiler senang tanpa beralih ke @SuppressWarnings.
Saya percaya masalah di sini adalah bahwa kompiler perlu mencari tahu apa jenis konkret array untuk dibuat. Jika metode ini tidak generik, kompiler dapat menggunakan informasi tipe dari metode. Jika metode ini generik, ia mencoba mencari tahu tipe array berdasarkan parameter yang digunakan saat doa. Jika tipe parameternya homogenik, tugas itu mudah. Jika mereka berbeda, kompiler mencoba menjadi terlalu pintar menurut saya dan membuat array generik tipe-serikat. Maka terasa wajib untuk memperingatkan Anda tentang hal itu. Solusi yang lebih sederhana adalah membuat Object [] ketika tipe tidak dapat dipersempit dengan lebih baik. Solusi di atas hanya memaksakan hal itu.
Untuk memahami ini lebih baik, bermain-main dengan doa ke metode daftar di atas dibandingkan dengan metode list2 berikut.
sumber
Anda dapat menambahkan @SafeVarargs ke metode sejak Java 7, dan Anda tidak perlu membuat catatan pada kode klien.
sumber
Anda dapat memiliki kelebihan metode. Ini tidak menyelesaikan masalah Anda tetapi meminimalkan jumlah peringatan (dan ya, ini peretasan!)
sumber
Ini adalah masalah yang sangat mudah untuk dipecahkan: Gunakan
List<T>
!Susunan jenis referensi harus dihindari.
Dalam versi Java saat ini (1.7), Anda dapat menandai metode
@SafeVargs
yang akan menghapus peringatan dari pemanggil. Hati-hati dengan itu, dan Anda masih lebih baik tanpa array warisan.Lihat juga Peringatan Kompiler yang Ditingkatkan dan Kesalahan Saat Menggunakan Parameter Formal yang Tidak Dapat Diperbaiki dengan catatan teknis Metode Varargs .
sumber
Ketika bekerja dengan array tipe generik, saya terpaksa memberikan referensi ke tipe generik. Dengan itu, saya benar-benar dapat melakukan kode generik, menggunakan java.lang.reflect.Array.
http://java.sun.com/javase/6/docs/api/java/lang/reflect/Array.html
sumber