ProgrammatieBackend ontwikkelaar

Vertel over de belangrijkste aspecten van het werken met generics in Java en welke details belangrijk zijn voor veilig gebruik?

Slaag voor sollicitatiegesprekken met de Hintsage AI-assistent

Antwoord.

Generics stellen ons in staat om klassen, interfaces en methoden met typeparameters te maken, wat typecontrole op compile-tijd mogelijk maakt en helpt om ClassCastException te voorkomen.

Belangrijkste kenmerken en valkuilen:

  • Type Erasure: Bij de compilatie wordt informatie over typeparameters gewist, waardoor je bijvoorbeeld geen array van generiek type kunt maken: new List<String>[10] — compileerfout.
  • Beperkingen op gebruik:
    • Je kunt geen instanties van geparametriseerd type maken: T obj = new T();
    • Je kunt instanceof niet gebruiken met geparametriseerde types: if(obj instanceof List<String>) — fout.
    • Je kunt geen statische velden van geparametriseerde types maken.
  • Wildcards: ? extends T — covariant (lezen), ? super T — contravariant (schrijven).
  • PECS-principe (Producer Extends, Consumer Super): Als je alleen wilt lezen — gebruik extends, als je wilt schrijven — super.

Voorbeeld:

// Covariante benadering voor lezen void printNumbers(List<? extends Number> numbers) { for (Number n : numbers) { System.out.println(n); } } // Contravariante benadering voor schrijven void addIntegers(List<? super Integer> list) { list.add(10); } }

Vraag met een valstrik.

Vraag: "Wat is het verschil tussen List<Object> en List<?>? Kan ik elk object in List<?> plaatsen?"

Antwoord: Nee, in List<?> kan je niets toevoegen (behalve null), omdat de compiler niet weet welk type parameter daar is. In List<Object> kan je wel elk object toevoegen.

Voorbeeld:

List<?> list1 = new ArrayList<String>(); // list1.add("test"); // Compileerfout! List<Object> list2 = new ArrayList<>(); list2.add("test"); // OK

Voorbeelden van reële fouten door onbekendheid met de details van het onderwerp.


Verhaal

Het ontwikkelingsteam probeerde een cache te implementeren op basis van een geparametriseerde array T[]. Door type erasure en de onmogelijkheid om arrays van generiek type te maken, werkte de oplossing niet zoals verwacht: het resulteerde in een Object[] array, wat leidde tot ClassCastException bij runtime casts.


Verhaal

In een van de microservices probeerde een ontwikkelaar een receiver te implementeren, die List<?> als parameter gebruikte, en probeerde de collectie te wijzigen. Dit leidde tot een compileerfout en uitstel van de release, omdat de logica moest worden herzien met inachtneming van PECS.


Verhaal

Voor een project voor integratie met een extern systeem maakte een ontwikkelaar een fout door een collectie van het ene type door een ander te overschrijven via een onbewerkte raw-type: List list = new ArrayList<String>(), wat leidde tot ClassCastException en service crashes in productie bij het proberen te casten van elementen naar andere types.