– Szia Amigo!

– Szia, Ellie!

"Ma Rishi és én mindent elmondunk a generikus gyógyszerekről."

– Várj, azt hiszem, már szinte mindent tudok.

– Majdnem mindent, de nem mindent.

"Tényleg? Oké, kész vagyok meghallgatni."

– Akkor kezdjük.

"A Java-ban az általánosok olyan osztályok, amelyek típusparaméterekkel rendelkeznek."

"Ami azt illeti, hogy miért találták ki a generikus gyógyszereket, lásd a kód megjegyzéseit:"

Példa
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
}

A probléma megoldása a Generics használatával:

Példa
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;
}

"Ez a kód egyszerűen nem fordítható le, és a fordítás során észreveszik a rossz adattípus hozzáadása okozta hibát."

– Igen, ezt már tudom.

"Rendben, jó. Az ismétlés a tanulás anyja."

"A Java készítői azonban egy kicsit lusták voltak, amikor generikusokat készítettek. Ahelyett, hogy teljes értékű típusokat készítettek volna paraméterekkel, belecsúsztak egy sima optimalizálásba. A valóságban nem adtak hozzá semmilyen információt a típusparaméterekről a generikusokhoz. Ehelyett az összes varázslat fordul elő az összeállítás során."

Kód generikusokkal
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);
}
Mi történik valójában
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);
}

– Ez sima.

"Igen, de ennek a megközelítésnek van egy mellékhatása.  A típusparaméterekről semmilyen információ nem tárolódik egy általános osztályon belül. Ez a megközelítés később típustörlés  néven vált ismertté ."

"Más szóval, ha van saját osztályod típusparaméterekkel, akkor az osztályon belül nem használhatsz rájuk vonatkozó információkat."

Kód generikusokkal
class Zoo<T>
{
 ArrayList<T> pets = new ArrayList<T>();

 public T createAnimal()
 {
  T animal = new T();
  pets.add(animal)
  return animal;
 }
}
Mi történik valójában
class Zoo
{
 ArrayList pets = new ArrayList();

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

"A fordítás során minden paramétertípust lecserélnek Object-re. Az osztályon belül pedig nincs információ a neki átadott típusról."

– Igen, egyetértek, ez nem a legjobb.

"Nem olyan ijesztő. Később elmondom, hogyan lehet megkerülni ezt a problémát."

De van több is. A Java segítségével megadhat szülőtípust a típusparaméterekhez. Erre az extends kulcsszót használjuk. Például:

Kód generikusokkal
class Zoo<T extends Cat>
{
 T cat;

 T getCat()
 {
  return cat;
 }

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

 String getCatName()
 {
  return this.cat.getName();
 }
}
Mi történik valójában
class Zoo
{
 Cat cat;

 Cat getCat()
 {
  return cat;
 }

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

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

"Jegyezz meg két tényt:"

"Először is, nem adhatsz át akármilyen típust paraméterként – csak egy macskát vagy egy olyan osztályt adhatsz át, amely örökli a Cat-et."

"Másodszor, az Állatkert osztályon belül a T típusú változók mostantól hívhatják a Cat osztály metódusait.  A jobb oldali oszlop megmagyarázza, hogy miért (mert a Cat mindenhol, ahol T van, fel lesz cserélve)"

"Igen. Ha azt mondjuk, hogy a Cat vagy a Cat egy alosztálya típus argumentumként kerül átadásra, akkor biztosak vagyunk benne, hogy a T típusban mindig a Cat osztály metódusai lesznek."

– Hát, ez okos.