ProgrammatieBackend ontwikkelaar

Leg uit hoe de methode resolutie volgorde (method resolution order) werkt bij erfelijkheid in Java en welke valkuilen er kunnen zijn.

Slaag voor sollicitatiegesprekken met de Hintsage AI-assistent

Antwoord.

In Java gebeurt de resolutie van overbelasting (overloading) en overschrijving (overriding) van methoden volgens bepaalde regels. Bij overbelasting kiest de compiler de meest geschikte methode uit alle versies tijdens de compilatie, op basis van het type argumenten op het moment van aanroep.

Belangrijke punten:

  • Als er overbelaste methoden zijn in alle klassen en superklassen, worden eerst de hoogste mogelijke overeenkomsten in de huidige klasse gezocht, dan in de superklassen.
  • De keuze van de methode vindt plaats tijdens de compilatie, en niet tijdens de uitvoering.
  • Type-conversies (widening, autoboxing, varargs) worden indien nodig toegepast.

Voorbeeld:

class Super { void print(Number n) { System.out.println("Super Number"); } } class Sub extends Super { void print(Integer i) { System.out.println("Sub Integer"); } } ... Sub s = new Sub(); s.print(5); // Sub Integer s.print(5.0); // Super Number

Hier zal print(Integer) worden aangeroepen voor een argument van het type Integer, terwijl voor het type Double de oudermethode wordt aangeroepen.

Misleidende vraag.

Als in de afgeleide klasse een methode is overschreven (override) en overbelast (overload), welke wordt dan aangeroepen bij polymorfisme?

Antwoord: Bij polymorfisme wordt altijd de versie van de methode gekozen op basis van het werkelijke type van het object voor overschreven methoden (overriding). Voor overbelaste methoden is de keuze gebaseerd op het type referentie en gebeurt dit tijdens de compilatie.

class A { void test(Number n) { System.out.println("A:Number"); } } class B extends A { void test(Integer n) { System.out.println("B:Integer"); } @Override void test(Number n) { System.out.println("B:Number"); } } ... A obj = new B(); obj.test(1); // Roept B:Number aan, ondanks dat test(Integer) bestaat

Voorbeelden van echte fouten door gebrek aan kennis van de subtiliteiten van het onderwerp.


Verhaal

Een ontwikkelaar voegde een overbelaste versie van een methode toe in de subklasse, in de veronderstelling dat deze zou worden aangeroepen voor alle afgeleiden. Het werd duidelijk in productie dat het aanroepen via een referentie van de bovenliggende klasse leidde tot de keuze van de methode op basis van het type referentie, en niet het object. Uiteindelijk werd de benodigde logica niet uitgevoerd.


Verhaal

In een groot project werd per ongeluk de methode equals(Object) overbelast met de handtekening equals(MyClass obj), in de veronderstelling dat deze de standaard equals zou vervangen. Bij vergelijking in HashSet-collecties werkte de standaard equals(Object), wat leidde tot inconsistentie in de logica en verlies van gegevens.


Verhaal

Bij het toevoegen van een nieuwe versie van de methode met varargs aan de hiërarchie van klassen, leek het erop dat de juiste versie voor arrays zou worden aangeroepen. Echter, bij het expliciet doorgeven van een array, koos de compiler niet de juiste overbelasting, waardoor de verwerking ongeldig was en de bug lang onopgemerkt bleef.