Menu

Java Methodenüberladung: gleicher Name, andere Parameter

Wie die Methodenüberladung in Java mehreren Methoden erlaubt, sich einen Namen zu teilen, aber unterschiedliche Parameter zu nehmen, wie der Compiler eine Überladung auswählt und welche Mehrdeutigkeitsfallen zu vermeiden sind.

Diese Seite enthält ausführbare Editoren - bearbeiten, ausführen und Ausgabe sofort sehen.

Ein Name, mehrere Versionen

Auf der vorherigen Seite hast du gesehen, wie die Parameter einer Methode festlegen, was sie akzeptiert. Die Methodenüberladung geht noch weiter: Du kannst mehreren Methoden denselben Namen geben, solange sich ihre Parameterlisten unterscheiden. Der Compiler behandelt sie als eigenständige Methoden und wählt anhand der übergebenen Argumente die passende aus.

Deshalb gibt System.out.println problemlos einen int, einen String, einen boolean oder einen double aus - es gibt nicht ein einziges println, sondern viele Überladungen, die sich den Namen teilen. Du schreibst den gemeinten Aufruf, und der Compiler ordnet ihn der passenden Version zu.

Beide Methoden heißen square, aber eine nimmt einen int und die andere einen double. Das Literal 5 ist ein int, daher läuft die erste Überladung; 2.5 ist ein double, daher läuft die zweite.

Was als unterschiedliche Überladung zählt

Überladungen müssen sich in ihrer Parameterliste unterscheiden - das heißt in mindestens einem der folgenden Punkte:

  • eine andere Anzahl von Parametern,
  • andere Parametertypen oder
  • eine andere Reihenfolge der Typen.

Jeder Aufruf hat eine Parameterliste, die genau zu einer der drei join-Methoden passt, also gibt es keine Verwechslung.

Der Rückgabetyp zählt nicht

Eine häufige Anfängerfalle: zu versuchen, allein über den Rückgabetyp zu überladen. Der Rückgabetyp ist nicht Teil der Signatur, die der Compiler verwendet, daher lässt sich dies nicht kompilieren:

// Kompiliert NICHT - gleicher Name, gleiche Parameter, nur der Rückgabetyp unterscheidet sich
static int   value() { return 1; }
static double value() { return 1.0; }   // Fehler: value() ist bereits definiert

Der Compiler kann sie nicht auseinanderhalten, denn an einer Aufrufstelle wie value() deutet nichts in den Argumenten darauf hin, welche du meinst. Du darfst Überladungen unterschiedliche Rückgabetypen geben, aber nur, wenn sich ihre Parameterlisten bereits unterscheiden.

Wie Java eine Überladung auswählt

Wenn mehr als eine Überladung deine Argumente akzeptieren könnte, wählt Java die spezifischste und bevorzugt eine exakte Typübereinstimmung gegenüber einer erweiternden Umwandlung. Sieh dir an, was mit einem int-Argument passiert:

show(7) passt exakt zu int, obwohl long und double nach einer Erweiterung ebenfalls eine 7 aufnehmen könnten. Erst wenn die exakte Überladung entfernt würde, würde der Compiler int zu long und dann zu double erweitern. Diese Auflösung wird vollständig zur Kompilierzeit entschieden, anhand der deklarierten Typen deiner Argumente.

Achtung bei mehrdeutigen Aufrufen

Wenn keine einzelne Überladung eindeutig die beste Übereinstimmung ist, weigert sich der Compiler zu raten und meldet einen Fehler. Das passiert am häufigsten mit null, das zu jedem Referenztyp passt:

static void handle(String s) { }
static void handle(StringBuilder b) { }

handle(null);   // Fehler: die Referenz auf handle ist mehrdeutig

Beide Überladungen akzeptieren null, und keine ist spezifischer, daher kompiliert der Aufruf nicht. Behebe es, indem du den Typ mit einem Cast explizit machst - handle((String) null) - oder das Design so änderst, dass die Überladungen nicht kollidieren. Dieselbe Vorsicht gilt beim Mischen von Autoboxing und Erweiterung; halte Überladungssätze einfach genug, damit jeder Aufruf einen offensichtlichen Gewinner hat.

Konstruktoren überladen

Überladung ist nicht auf gewöhnliche Methoden beschränkt - Konstruktoren nutzen sie ständig, um mehrere Wege zum Erstellen eines Objekts anzubieten. Ein parameterloser Konstruktor kann mit this(...) an einen vollständigeren delegieren:

Beide Konstruktoren teilen sich den Namen Point, unterscheiden sich aber in der Parameteranzahl, genau wie überladene Methoden. Das Delegieren mit this(...) hält die Initialisierungslogik an einer Stelle.

Überladung vs. Überschreibung

Diese beiden klingen ähnlich, haben aber nichts miteinander zu tun:

  • Überladung - gleicher Name, unterschiedliche Parameterlisten, in derselben Klasse. Der Compiler wählt die Version zur Kompilierzeit. Es geht darum, Varianten einer Operation anzubieten.
  • Überschreibung - eine Unterklasse definiert eine geerbte Methode mit gleichem Namen und gleichen Parametern neu. Java wählt die Version zur Laufzeit anhand des tatsächlichen Objekttyps. Es geht darum, Verhalten zu ersetzen (du begegnest ihr bei Vererbung und Polymorphie).

Sind die Parameterlisten identisch, überschreibst du (oder verursachst einen Fehler wegen doppelter Methode in derselben Klasse); unterscheiden sie sich, überlädst du.

Als Nächstes: Varargs

Mit der Überladung kannst du join(a, b) und join(a, b, c) als getrennte Methoden schreiben - aber was, wenn du eine beliebige Anzahl von Argumenten akzeptieren willst, ohne für jede Anzahl eine Überladung zu deklarieren? Javas varargs-Syntax erlaubt es einer einzigen Methode, eine Argumentliste variabler Länge zu nehmen, und das ist das Thema der nächsten Seite.

Häufig gestellte Fragen

Was ist Methodenüberladung in Java?

Methodenüberladung bedeutet, mehrere Methoden mit demselben Namen in derselben Klasse zu definieren, jede mit einer anderen Parameterliste (andere Anzahl von Parametern, andere Typen oder eine andere Reihenfolge der Typen). Der Compiler entscheidet anhand der übergebenen Argumente, welche Version aufgerufen wird, indem er sie mit den Parametern jeder Überladung abgleicht. Das ist eine Entscheidung zur Kompilierzeit, nicht zur Laufzeit.

Können sich zwei Methoden in Java nur durch den Rückgabetyp unterscheiden?

Nein. Der Rückgabetyp ist für die Überladung kein Teil der Signatur einer Methode, daher sind int total() und double total() in derselben Klasse ein Kompilierfehler. Überladungen müssen sich in ihrer Parameterliste unterscheiden: in der Anzahl, den Typen oder der Reihenfolge der Parameter. Der Rückgabetyp darf abweichen, aber nur zusätzlich zu einem Unterschied bei den Parametern, nie für sich allein.

Was ist der Unterschied zwischen Überladung und Überschreibung in Java?

Überladung sind mehrere Methoden mit gleichem Namen, aber unterschiedlichen Parametern in derselben Klasse, die der Compiler zur Kompilierzeit auflöst. Überschreibung ist, wenn eine Unterklasse eine geerbte Methode mit gleichem Namen und gleichen Parametern neu definiert; das wird zur Laufzeit anhand des tatsächlichen Objekttyps aufgelöst. Bei der Überladung geht es darum, Varianten anzubieten; beim Überschreiben darum, Verhalten zu ersetzen.

Coddy programming languages illustration

Lerne mit Coddy zu programmieren

LOS GEHT'S