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
return
enden.
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
4
true
ist, wird die Methode sofort mit einemfalse
verlassen und die weiteren Zeilen werden gar nicht weiter ausgeführt. - Wenn die Bedingung in Zeile
4
false
ist, die Bedingung in Zeile5
abertrue
, wird die Methode sofort mit einemtrue
verlassen und die weiteren Zeilen werden gar nicht weiter ausgeführt. - Wenn die Bedingung in den Zeilen
4
und5
jeweilsfalse
sind, die Bedingung in Zeile6
abertrue
, wird die Methode sofort mit einemfalse
verlassen und die weiteren Zeilen werden gar nicht weiter ausgeführt. -
ab Zeile
7
wissen wir also,- dass
other
nicht gleichnull
ist, - dass
this
nicht gleichother
ist und - dass
this
undother
den gleichen Laufzeittyp haben (this
ist vom LaufzeittypViereck
undother
dann auch → andernfalls wäre die Methode in Zeile6
verlassen worden).
- dass
Alle Ablaufpfade der Methode müssen mit return
enden¶
Alle Pfade durch die Methode müssen mit einem
return
enden.
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).