return¶
Da wir das bis jetzt noch nicht ausführlich genug erläutert haben, beschäftigen wir uns hier nochmal mit return. Eine Methode, die einen Rückgabetyp hat (also nicht void), muss einen Wert von diesem Typ zurückgeben:
public Type method()
{
// Implementierung der Methode
return valueOfType;
}
Dabei sind einige Sachen zu beachten:
- Nach der
return-Anweisung wird die Methode sofort verlassen. - Alle Pfade durch die Methode müssen mit einem
returnenden.
Sofortiges Verlassen nach return¶
Nach der
return-Anweisung wird die Methode sofort verlassen!
Anweisungen, die nach der return-Anweisung kommen, sind nicht mehr erreichbar, sogenannter dead code (oder unreachable code). Beispiel:
1 2 3 4 5 6 7 8 9 10 | |
Die Methode sum(int n) berechnet die Summe aller Zahlen von 1 bis n. Diese Summe wird zurückgegeben. In der Methodendeklaration (im Methodenkopf) wird vereinbart, dass die Methode einen Wert vom Typ int zurückgibt. Dies passiert auch (in Zeile 8). sum ist vom Typ int. Nach Aufruf der return-Anweisung in Zeile 8 wird die Methode sofort verlassen. Das führt dazu, dass die Anweisung in Zeile 9 nie ausgeführt werden kann. Es handelt sich dabei um unreachable code. Dies wird zum Glück vom Compiler erkannt - das Programm lässt sich gar nicht compilieren.
In vielen Methoden wird der Fakt ausgenutzt, dass die Methode bei einem return sofort verlassen wird. Betrachten wir z.B. eine Methode contains(int[] ia, int element), welche prüft, ob element im Array ia enthalten ist oder nicht:
public boolean contains(int[] ia, int element)
{
for (int index = 0; index < ia.length; index++)
{
if(ia[index] == element)
{
return true;
}
}
return false;
}
Sobald das element im Array ia gefunden wird (Zeile 5), wird return true aufgerufen und die Methode somit sofort verlassen. Es wird also auch die for-Schleife nicht weiter fortgesetzt und es werden keine weiteren Elemente aus dem Array betrachtet. Das führt auch dazu, dass in Zeile 10 klar ist, dass das element nicht im Array vorkommt, denn bis dahin wurden alle Elemente aus dem Array betrachtet und offensichtlich war die Bedingung ia[index] == element niemals true, denn ansonsten würden wir gar nicht bis Zeile 10 kommen. Wir wissen dort also, dass das element nicht im Array vorkommt und können somit ein false zurückgeben.
Ähnliches nutzen wir in der equals()-Methode aus. Hier nochmal das Beispiel aus Viereck:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | |
- Wenn die Bedingung in Zeile
4trueist, wird die Methode sofort mit einemfalseverlassen und die weiteren Zeilen werden gar nicht weiter ausgeführt. - Wenn die Bedingung in Zeile
4falseist, die Bedingung in Zeile5abertrue, wird die Methode sofort mit einemtrueverlassen und die weiteren Zeilen werden gar nicht weiter ausgeführt. - Wenn die Bedingung in den Zeilen
4und5jeweilsfalsesind, die Bedingung in Zeile6abertrue, wird die Methode sofort mit einemfalseverlassen und die weiteren Zeilen werden gar nicht weiter ausgeführt. -
ab Zeile
7wissen wir also,- dass
othernicht gleichnullist, - dass
thisnicht gleichotherist und - dass
thisundotherden gleichen Laufzeittyp haben (thisist vom LaufzeittypViereckundotherdann auch → andernfalls wäre die Methode in Zeile6verlassen worden).
- dass
Alle Ablaufpfade der Methode müssen mit return enden¶
Alle Pfade durch die Methode müssen mit einem
returnenden.
Angenommen, wir haben ein Array vom Typ String[] und wollen in einer Methode getStringAtIndex(String[] arr, int index) den String zurückgeben, der in dem Array beim Index index gespeichert ist. Eine mögliche Implementierung könnte so aussehen:
1 2 3 4 | |
Diese Methode ist prinzipiell korrekt, hat aber eine große Schwäche. Wenn index gar kein korrekter Index für das arr-Array ist, dann wirft der Aufruf dieser Methode eine ArraysIndexOutOfBounds-Exception. Um dies zu verhindern, könnte man die Methode nun wie folgt erweitern:
1 2 3 4 5 6 7 | |
Jetzt prüfen wir zunächst, ob der index auch tatsächlich korrekt ist und vermeiden so eine eventuelle ArraysIndexOutOfBounds-Exception. Aber die Methode lässt sich so nicht compilieren! Der Compiler gibt die Fehlermeldung
This method must return a result of type String
an. Das Problem ist, dass die Methode keinen String zurückgibt, wenn die Bedingung in Zeile 3 false ist! Es muss also jeder mögliche Pfad durch die Methode bei einem return enden! Das führt dazu, dass in Methoden, die ein Objekt zurückgeben müssen (der Rückgabetyp der Methode also ein Referenztyp ist), häufig für Ausnahmefälle ein null zurückgegeben wird:
1 2 3 4 5 6 7 8 9 10 11 | |
Die obige Methode ist nun korrekt und kann compiliert werden. Wir sollten uns aber merken, dass wir in Zukunft versuchen, die Rückgabe von null zu vermeiden. Derzeit haben wir aber keine andere Möglichkeit und können die Methode nur so formulieren. Später werfen wir stattdessen in der Methode eine eigene Exception für den Fall, dass der index nicht korrekt ist oder geben ein Optional-Objekt zurück (siehe z.B. hier oder hier).