Saya mengalami beberapa masalah dalam menavigasi aturan Java untuk menyimpulkan parameter tipe generik. Pertimbangkan kelas berikut, yang memiliki parameter daftar opsional:
import java.util.Collections;
import java.util.List;
public class Person {
private String name;
private List<String> nicknames;
public Person(String name) {
this(name,Collections.emptyList());
}
public Person(String name,List<String> nicknames) {
this.name = name;
this.nicknames = nicknames;
}
}
Kompiler Java saya memberikan kesalahan berikut:
Person.java:9: The constructor Person(String, List<Object>) is undefined
Tapi Collections.emptyList()
tipe pengembalian <T> List<T>
, bukan List<Object>
. Menambahkan gips tidak membantu
public Person(String name) {
this(name,(List<String>)Collections.emptyList());
}
hasil panen
Person.java:9: inconvertible types
Menggunakan EMPTY_LIST
bukanemptyList()
public Person(String name) {
this(name,Collections.EMPTY_LIST);
}
hasil panen
Person.java:9: warning: [unchecked] unchecked conversion
Sedangkan perubahan berikut membuat kesalahan hilang:
public Person(String name) {
this.name = name;
this.nicknames = Collections.emptyList();
}
Adakah yang bisa menjelaskan aturan pengecekan jenis apa yang saya hadapi di sini, dan cara terbaik untuk mengatasinya? Dalam contoh ini, contoh kode akhir memuaskan, tetapi dengan kelas yang lebih besar, saya ingin dapat menulis metode mengikuti pola "parameter opsional" ini tanpa menggandakan kode.
Untuk kredit tambahan: Kapan tepat untuk menggunakan EMPTY_LIST
sebagai lawan emptyList()
?
sumber
Jawaban:
Masalah yang Anda temui adalah meskipun metode
emptyList()
kembaliList<T>
, Anda belum memberikannya dengan tipe, jadi default untuk kembaliList<Object>
. Anda dapat memberikan parameter type, dan kode Anda berperilaku seperti yang diharapkan, seperti ini:Sekarang ketika Anda melakukan penugasan langsung, kompiler dapat mengetahui parameter tipe generik untuk Anda. Ini disebut inferensi tipe. Misalnya, jika Anda melakukan ini:
maka
emptyList()
panggilan akan kembali dengan benar aList<String>
.sumber
this
harus menjadi pernyataan pertama dalam konstruktor.Anda ingin menggunakan:
Jika Anda melihat sumber untuk blankList apa Anda melihat bahwa itu sebenarnya hanya a
sumber
metode blankList memiliki tanda tangan ini:
Bahwa
<T>
sebelum daftar kata berarti bahwa itu menyimpulkan nilai parameter generik T dari jenis variabel hasil ditugaskan. Jadi dalam hal ini:Nilai kembali kemudian direferensikan secara eksplisit oleh variabel tipe
List<String>
, sehingga kompiler dapat mengetahuinya. Pada kasus ini:Tidak ada variabel pengembalian eksplisit untuk kompiler yang digunakan untuk mengetahui tipe generik, jadi defaultnya adalah
Object
.sumber