Einführung
Wie wir wissen, ist Java eine objektorientierte Programmiersprache. Das ist das Grundkonzept, denn Die Grundlage der Grundlagen ist, dass alles ein Objekt ist. Objekte werden durch Klassen beschrieben.
Klassen wiederum haben Zustand und Verhalten. Beispielsweise kann ein Bankkonto einen Zustand in Form des Geldbetrags auf dem Konto haben und das Verhalten aufweisen, dass sich der Kontostand erhöht und verringert. Verhalten wird in Java mithilfe von Methoden implementiert. Wie Methoden beschrieben werden, erfahren Sie gleich zu Beginn Ihrer Java-Lernreise. Zum Beispiel im offiziellen Tutorial von Oracle: „
Defining Methods “. Hier gibt es zwei wichtige Aspekte:
- Jede Methode hat eine Signatur. Die Signatur besteht aus dem Methodennamen und seinen Eingabeparametern;
- Methoden müssen einen Rückgabetyp angeben;
- Der Rückgabetyp ist nicht Teil der Methodensignatur.
Dies ist wiederum eine Folge der Tatsache, dass Java eine stark typisierte Sprache ist und der Compiler möglichst im Voraus wissen möchte, welche Typen wo verwendet werden. Nochmals, um uns vor Fehlern zu schützen. Im Allgemeinen ist alles zum Guten. Nun, das scheint mir wieder einmal eine Kultur des Umgangs mit Daten in uns zu wecken. Bei Methoden wird also der Werttyp angegeben. Und um denselben Wert von den Methoden zurückzugeben, wird das Schlüsselwort verwendet
return
.
Schlüsselwort-Return-Anweisung in Java
Das Schlüsselwort „Anweisung
return
“ bezieht sich auf „Kontrollflussanweisungen“, wie im Oracle-Tutorial „
Kontrollflussanweisungen “ erläutert. Wie man Werte zurückgibt, können Sie auch im offiziellen Tutorial lesen: „
Returning a Value from a Method “. Der Compiler überwacht nach besten Kräften sorgfältig, dass der von einer Methode zurückgegebene Wert mit dem von der Methode angegebenen Rückgabewerttyp übereinstimmt. Nehmen wir als Beispiel
die Online-IDE von Tutorialspoint . Schauen wir uns das Originalbeispiel an:
public class HelloWorld {
public static void main(String []args) {
System.out.println("Hello World");
}
}
Wie wir sehen können, wird hier eine Methode ausgeführt
main
, die den Einstiegspunkt in das Programm darstellt. Codezeilen werden von oben nach unten ausgeführt. Unsere
main
Methode kann keine Werte zurückgeben, sonst erhalten wir eine Fehlermeldung: „
Error: Main method must return a value of type void
“. Daher wird die Methode einfach auf dem Bildschirm ausgegeben. Lassen Sie uns nun den Empfang der Zeichenfolge in eine separate Methode zum Empfangen der Nachricht verlagern:
public class HelloWorld {
public static void main(String []args) {
System.out.println(getHelloMessage());
}
public static String getHelloMessage() {
return "Hello World";
}
}
Wie wir sehen können,
return
haben wir mit dem Schlüsselwort den Rückgabewert angegeben, den wir später in der Methode verwendet haben
println
. In der Beschreibung (Definition) der Methode
getHelloMessage
haben wir angegeben, dass sie uns zurückgibt
String
. Dadurch kann der Compiler überprüfen, ob die Aktionen der Methode mit der Art und Weise ihrer Deklaration übereinstimmen. Natürlich kann der Typ des in der Methodendefinition angegebenen Rückgabewerts breiter sein als der Typ des vom Code zurückgegebenen Werts, d. h. Hauptsache, die Typen sind aufeinander reduziert. Andernfalls erhalten wir einen Kompilierungszeitfehler: „
error: incompatible types
“. Übrigens stellte sich wahrscheinlich sofort die Frage: Warum
return
gilt das für Programmflusskontrolloperatoren? Sondern weil es den normalen Ablauf des Programms von oben bis unten stören kann. Zum Beispiel:
public class HelloWorld {
public static void main(String []args){
if (args.length == 0) {
return;
}
for (String arg : args) {
System.out.println(arg);
}
}
}
Wie aus dem Beispiel hervorgeht, unterbrechen wir die Ausführung der Methode,
main
wenn unser Java-Programm ohne Parameter aufgerufen wird. Es ist wichtig zu bedenken, dass der Code nicht mehr zugänglich ist, wenn Sie ihn
return
haben. Und unser intelligenter Compiler wird dies bemerken und Ihnen die Ausführung eines solchen Programms nicht erlauben. Dieser Code lässt sich beispielsweise nicht kompilieren:
public static void main(String []args) {
System.out.println("1");
return;
System.out.println("2");
}
Es gibt einen schmutzigen Hack, um das zu umgehen. Zum Beispiel zu Debug-Zwecken oder aus einem anderen Grund. Der obige Code kann behoben werden, indem man ihn
return
in
if
einen Block einschließt:
if (2==2) {
return;
}
Return-Anweisung in der Fehlerbehandlung
Es gibt einen sehr kniffligen Umstand: Wir können ihn
return
in Verbindung mit der Fehlerbehandlung nutzen. Ich möchte gleich sagen, dass es sehr, sehr schlecht ist, es
return
in einem Block zu verwenden, also sollte man es vermeiden.
catch
Aber wir brauchen ein Beispiel, oder? Da ist er:
public class HelloWorld {
public static void main(String []args) {
System.out.println("Value is: " + getIntValue());
}
public static int getIntValue() {
int value = 1;
try {
System.out.println("Something terrible happens");
throw new Exception();
} catch (Exception e) {
System.out.println("Catched value: " + value);
return value;
} finally {
value++;
System.out.println("New value: " + value);
}
}
}
Auf den ersten Blick scheint es, dass 2 zurückgegeben werden sollte, da
finally
es immer ausgeführt wird. Aber nein, der Wert ist 1 und die Änderung der Variablen in
finally
wird ignoriert. Wenn es außerdem
value
ein Objekt enthielte und wir
finally
sagten
value = null
, würde es
catch
immer noch einen Verweis auf das Objekt zurückgeben, nicht
null
. Aber vom Block aus hätte
finally
der Operator korrekt gearbeitet.
return
Kollegen werden Ihnen für ein solches Geschenk offensichtlich nicht danken.
void.class
Und schlussendlich. Sie können eine seltsame Konstruktion schreiben wie
void.class
. Es scheint, warum und worum geht es? Tatsächlich kann dies in verschiedenen Frameworks und kniffligen Fällen, in denen
die Java Reflection API verwendet wird , sehr notwendig sein. Sie können beispielsweise überprüfen, welchen Typ eine Methode zurückgibt:
import java.lang.reflect.Method;
public class HelloWorld {
public void getVoidValue() {
}
public static void main(String[] args) {
for (Method method : HelloWorld.class.getDeclaredMethods()) {
System.out.println(method.getReturnType() == void.class);
}
}
}
Dies kann in Test-Frameworks nützlich sein, bei denen es notwendig ist, den echten Methodencode zu ersetzen. Dazu müssen Sie jedoch verstehen, wie sich diese Methode verhält (d. h. welche Typen sie zurückgibt). Es gibt eine zweite Möglichkeit, die Methode
main
aus dem obigen Code zu implementieren:
public static void main (String[] args) {
for (Method method : HelloWorld.class.getDeclaredMethods()) {
System.out.println(method.getReturnType() == Void.TYPE);
}
}
Eine ziemlich interessante Diskussion über den Unterschied zwischen ihnen kann auf stackoverflow gelesen werden:
Was ist der Unterschied zwischen java.lang.Void und void? #Wjatscheslaw
GO TO FULL VERSION