"Hai, Amigo!"

"Hai, Ellie!"

"Hari ini, Rishi dan saya akan memberitahu anda semua tentang generik."

"Tunggu, saya rasa saya sudah tahu hampir segala-galanya."

"Hampir semuanya, tetapi bukan semuanya."

"Betul ke? OK, saya sedia mendengar."

"Kalau begitu mari kita mulakan."

"Di Java, generik ialah kelas yang mempunyai parameter jenis."

"Mengenai sebab generik dicipta, lihat komen dalam kod:"

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
}

Bagaimana untuk menyelesaikan 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;
}

"Kod ini tidak akan dikompilkan, dan ralat yang disebabkan oleh penambahan jenis data yang salah akan diperhatikan semasa penyusunan."

"Ya, saya sudah tahu ini."

"Okay, bagus. Pengulangan adalah ibu kepada pembelajaran."

"Tetapi pencipta Java agak malas apabila mereka mencipta generik. Daripada membuat jenis lengkap dengan parameter, mereka tergelincir dalam pengoptimuman yang licin. Pada hakikatnya, mereka tidak menambah sebarang maklumat tentang parameter jenis pada generik. Sebaliknya, semua sihir berlaku semasa penyusunan."

Kod 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 sebenarnya yang berlaku
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 mempunyai kesan sampingan.  Tiada maklumat tentang parameter jenis disimpan di dalam kelas generik.  Pendekatan ini kemudiannya dikenali sebagai pemadaman jenis ."

"Dengan kata lain, jika anda mempunyai kelas anda sendiri dengan parameter jenis, anda tidak boleh menggunakan maklumat tentang mereka di dalam kelas."

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

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

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

"Semasa penyusunan, semua jenis parameter digantikan dengan Objek. Dan di dalam kelas tiada maklumat tentang jenis yang dihantar kepadanya."

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

"Taklah seram sangat. Nanti saya cerita macam mana nak atasi masalah ni."

Tetapi ada lagi. Java membolehkan anda menentukan jenis induk untuk parameter jenis. Kata kunci extends digunakan untuk ini. Sebagai contoh:

Kod 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 sebenarnya yang berlaku
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 boleh melepasi sebarang jenis sahaja sebagai parameter — anda hanya boleh melepasi Cat atau kelas yang mewarisi Cat."

"Kedua, di dalam kelas Zoo, pembolehubah jenis T kini boleh memanggil kaedah kelas Cat.  Lajur di sebelah kanan menerangkan sebabnya (kerana Cat akan digantikan di mana-mana terdapat T)"

"Ya. Jika kami mengatakan bahawa Cat atau subkelas Cat diluluskan sebagai hujah jenis, maka kami pasti jenis T akan sentiasa mempunyai kaedah kelas Cat."

"Nah, itu pandai."