"Hai, Amigo!"

"Hai, Elli!"

"Hari ini, Rishi dan aku akan memberitahumu semua tentang obat generik."

"Tunggu, kurasa aku sudah tahu hampir semuanya."

"Hampir semuanya, tapi tidak semuanya."

"Benarkah? Oke, aku siap mendengarkan."

"Kalau begitu mari kita mulai."

"Di Java, generik adalah kelas yang memiliki parameter tipe."

"Mengenai mengapa obat generik ditemukan, lihat komentar di kode:"

Contoh
ArrayList stringList = new ArrayList();
stringList.add("abc"); // Add a string to the list
stringList.add("abc"); // Add a string to the list
stringList.add( 1 ); // Add a number to the list

for(Object o: stringList)
{
 String s = (String) o; // There will be an exception here when we get to the integer
}

Cara mengatasi masalah menggunakan Generik:

Contoh
ArrayList<String> stringList = new ArrayList<String>();
stringList.add("abc"); // Add a string to the list
stringList.add("abc"); // Add a string to the list
stringList.add( 1 ); // There will be a compilation error here

for(Object o: stringList)
{
 String s = (String) o;
}

"Kode ini tidak dapat dikompilasi, dan kesalahan yang disebabkan oleh penambahan tipe data yang salah akan diketahui selama kompilasi."

"Ya, aku sudah tahu ini."

"Oke, bagus. Pengulangan adalah ibu dari pembelajaran."

"Tapi pencipta Java sedikit malas ketika mereka membuat generik. Alih-alih membuat tipe lengkap dengan parameter, mereka menyelipkan pengoptimalan yang apik. Pada kenyataannya, mereka tidak menambahkan informasi apa pun tentang parameter tipe ke generik. Sebaliknya, semua keajaiban terjadi selama kompilasi."

Kode dengan generik
List<String> strings = new ArrayList<String>();
strings.add("abc");
strings.add("abc");
strings.add( 1); // Compilation error

for(String s: strings)
{
 System.out.println(s);
}
Apa yang sebenarnya terjadi
List strings = new ArrayList();

strings.add((String)"abc");
strings.add((String)"abc");
strings.add((String) 1); // Compilation error

for(String s: strings)
{
 System.out.println(s);
}

"Itu licin."

"Ya, tetapi pendekatan ini memiliki efek samping.  Tidak ada informasi tentang parameter tipe yang disimpan di dalam kelas generik.  Pendekatan ini kemudian dikenal sebagai penghapusan tipe ."

"Dengan kata lain, jika Anda memiliki kelas sendiri dengan parameter tipe, Anda tidak dapat menggunakan informasi tentangnya di dalam kelas."

Kode dengan generik
class Zoo<T>
{
 ArrayList<T> pets = new ArrayList<T>();

 public T createAnimal()
 {
  T animal = new T();
  pets.add(animal)
  return animal;
 }
}
Apa yang sebenarnya terjadi
class Zoo
{
 ArrayList pets = new ArrayList();

 public Object createAnimal()
 {
  Object animal = new ???();
  pets.add(animal)
  return animal;
 }
}

"Selama kompilasi, semua tipe parameter diganti dengan Object. Dan di dalam kelas tidak ada informasi tentang tipe yang diteruskan ke sana."

"Ya, saya setuju, itu bukan yang terbaik."

"Tidak terlalu menakutkan. Akan kuberitahu nanti cara mengatasi masalah ini."

Tapi masih ada lagi. Java memungkinkan Anda menentukan tipe induk untuk parameter tipe. Kata kunci extends digunakan untuk ini. Misalnya:

Kode dengan generik
class Zoo<T extends Cat>
{
 T cat;

 T getCat()
 {
  return cat;
 }

 void setCat (T cat)
 {
  this.cat = cat;
 }

 String getCatName()
 {
  return this.cat.getName();
 }
}
Apa yang sebenarnya terjadi
class Zoo
{
 Cat cat;

 Cat getCat()
 {
  return cat;
 }

 void setCat(Cat cat)
 {
  this.cat = cat;
 }

 String getCatName()
 {
  return this.cat.getName();
 }
}

"Perhatikan dua fakta:"

"Pertama, Anda tidak bisa meneruskan tipe apa pun sebagai parameter — Anda hanya bisa meneruskan Cat atau kelas yang mewarisi Cat."

"Kedua, di dalam kelas Zoo, variabel bertipe T sekarang dapat memanggil metode kelas Cat.  Kolom di sebelah kanan menjelaskan alasannya (karena Cat akan diganti di mana pun ada T)"

"Ya. Jika kita mengatakan bahwa Cat atau subclass dari Cat dilewatkan sebagai argumen tipe, maka kita yakin bahwa tipe T akan selalu memiliki metode kelas Cat."

"Yah, itu pintar."