Geschiedenis van de vraag:
Generics werden geïntroduceerd in Java 5 om veilige interactie met typelijsten en methoden te waarborgen, echter werden ze geïmplementeerd met ondersteuning voor backward compatibility met eerder geschreven bytecode. Hiervoor werd het mechanisme van type erasure gebruikt.
Probleem:
De Java-compiler vereist strikte typificatie, maar tijdens de uitvoering weet de JVM niets over de typeparameters, en veel oude klassen en bibliotheken, inclusief de Java-collectiebibliotheek zelf, werken met universele "ruwe" typen (raw types). Zonder backward compatibility was het niet mogelijk om bestaande ontwikkelingen te ondersteunen.
Oplossing:
Type erasure is het proces waarbij geparameteriseerde types (generics) worden omgezet naar hun "ruwe" versies, zodat de JVM kan werken met de reeds bestaande bytecode zonder wijzigingen. Alle informatie over typeparameters wordt tijdens het compileren verwijderd, in plaats daarvan worden objecten van het type Object gebruikt (of een beperking, indien opgegeven via extends).
Voorbeeldcode:
List<String> stringList = new ArrayList<>(); stringList.add("hello"); String s = stringList.get(0); // get retourneert Object, maar de compiler voegt een cast toe
Belangrijke kenmerken:
List<String>, List<Integer>, enz. was.Kan je methoden alleen op basis van generics parameters overbelasten?
Nee. Door type erasure beschouwt de compiler methoden met dezelfde namen en verschillende generics parameters als gelijk, omdat de parameters verwijderd worden. Bijvoorbeeld,
// Compilatiefout! void process(List<String> list) { } void process(List<Integer> list) { }
Kan je een array van een generiek type maken?
Nee, niet rechtstreeks. Type erasure staat de JVM niet toe om een array van een specifiek generiek type op te slaan, bijvoorbeeld,
List<String>[] array = new List<String>[10]; // Compilatiefout
Je kunt omzeilen met een array van ruwe types, maar dat is onveilig:
List<String>[] array = (List<String>[]) new List[10];
Kan je het type van een generiek type op runtime controleren met instanceof?
Nee, omdat de informatie over parameters gewist wordt. Controle:
if (obj instanceof List<String>) { ... } // Compilatiefout
Correcter is om alleen het hoofdt-type te controleren:
if (obj instanceof List) { ... }
Een programmeur maakt een array van geparameteriseerde types om lijsten met verschillende parameters op te slaan. Uiteindelijk, na langdurig werken met het programma, ontstaat er een ClassCastException bij het ophalen van een object uit de array — typen worden niet gegarandeerd op runtime.
Voordelen:
Nadelen:
In plaats van arrays worden collecties gebruikt (bijvoorbeeld, List<List<String>>), en alle typecontroles worden gedelegeerd aan de compiler.
Voordelen:
Nadelen: