Kedua contoh ini setara, dan pada kenyataannya akan dikompilasi dengan bytecode yang sama.
Ada dua cara yang menambahkan tipe generik terbatas ke metode seperti pada contoh pertama Anda akan melakukan apa saja.
Melewati parameter tipe ke tipe lain
Kedua tanda tangan metode ini pada akhirnya sama dengan kode byte, tetapi kompiler memberlakukan keamanan tipe:
public static <T extends Animal> void addAnimals(Collection<T> animals)
public static void addAnimals(Collection<Animal> animals)
Dalam kasus pertama, hanya Collection
(atau subtipe) dari Animal
yang diizinkan. Dalam kasus kedua, a Collection
(atau subtipe) dengan tipe generik Animal
atau subtipe diperbolehkan.
Misalnya, yang berikut diperbolehkan dalam metode pertama tetapi tidak yang kedua:
List<Cat> cats = new ArrayList<Cat>();
cats.add(new Cat());
addAnimals(cats);
Alasannya adalah bahwa yang kedua hanya memungkinkan koleksi hewan, sedangkan yang pertama memungkinkan koleksi benda apa pun yang ditugaskan untuk hewan (yaitu subtipe). Perhatikan bahwa jika daftar ini adalah daftar hewan yang mengandung kucing, metode mana pun akan menerimanya: masalahnya adalah spesifikasi umum koleksi, bukan apa yang sebenarnya dikandungnya.
Mengembalikan benda
Waktu lain yang penting adalah dengan mengembalikan objek. Mari kita asumsikan ada metode berikut:
public static <T extends Animal> T feed(T animal) {
animal.eat();
return animal;
}
Anda dapat melakukan hal berikut dengan itu:
Cat c1 = new Cat();
Cat c2 = feed(c1);
Meskipun ini adalah contoh yang dibuat-buat, ada beberapa kasus yang masuk akal. Tanpa obat generik, metode ini harus kembali Animal
dan Anda perlu menambahkan tipe casting untuk membuatnya berfungsi (yang merupakan kompiler yang menambahkan kode byte di belakang layar).
addAnimals(List<Animal>)
dan menambahkan Daftar Kucing!