Generické datové typy (generics)

Pokud si vezmeme anglicko-český slovník, zjistíme, že v překladu to znamená něco obecně použitelného, tedy mohli bychom použít termínu zobecnění. A přesně tím generics jsou -- zobecněním.

Jak již víme, struktura tříd v Javě má společného předka, třídu Object. Tato skutečnost zjednodušuje implementaci nejednoho programu -- potřebujeme-li pracovat s nějakými objekty, o kterých tak úplně nevíme, co jsou zač, můžeme využít společného předka a pracovat s ním. Každý objekt v programu je totiž i instancí třídy Object. To v praxi umožňuje například snadnou implementaci spojových seznamů, hashovacích tabulek, ale například i využití reflexe.

Jakkoliv je společný předek jistě výhodou, přináší i některé obtíže. Uvažujme opět (spojový) seznam. Pracujeme-li v programu s nějakým, víme jenom, že je to seznam objektů a nic více. Samozřejmě si můžeme bokem pamatovat, že tam ukládáme jenom řetězce, ale to nic nemění na tom, že runtime systému je srdečně jedno, jaké objekty do seznamu vkládáme. Stejně tak, chceme-li z tohoto seznamu číst, získáváme zase jenom obecné objekty, které musíme explicitně přetypovat na řetězec (tj. třídu String). A opět -- ačkoliv jako programátoři víme, co v seznamu má být, obecně si nemůžeme být jisti, zda to tam skutečně je. Což vede buď k tomu, že se budeme ptát, zda získávaný objekt je skutečně řetězcem a až poté jej přetypujeme nebo budeme „riskovat“ runtime výjimku ClassCastException. Jak vidíme, nevýhody jsou a to docela významné.

Řešením v této situaci je příchod Javy verze 1.5, která mimojiné přináší i zmiňovaná generics. Opět využijeme našeho spojového seznamu. Vraťme se zpět k jeho definici. Co od něj vlastně požadujeme?

  • Aby byl seznamem čehokoliv a tak byl universální (což je stav popsaný výše)?

  • Nebo aby to byl seznam nějakého obecného, předem nedefinovaného typu a umožnil tento typ při vytvoření instance určit?

Jelikož předchozí otázky jsou řečnické, odpověď následuje ihned. Samozřejmě, že druhá uvedená možnost je lepší (už proto, že má veškerou sílu první možnosti, stačí nadefinovat, aby tím obecným typem byl Object). Ve zbytku textu si tedy ukážeme, jak toho generics docilují a jak je používat.