37 Stimmen

Warum ist die Rückkehr auch nach System.exit(0) erforderlich;

Betrachten Sie diese Funktion:

public boolean foo(){
   System.exit(1);
   //The lines beyond this will not be read
   int bar = 1;                  //L1
   //But the return statement is required for syntactically correct code
   return false;                 //L2

   //error here for unreachable code
   //int unreachable = 3;        //L3

}

Kann mir jemand erklären, warum L1 und L2, die sichtbar nicht erreichbar sind, keine Warnungen ausgeben, L3 aber schon.

50voto

biziclop Punkte 47795

Denn was den Compiler anbelangt, System.exit() ist nur ein weiterer Methodenaufruf.

Die Tatsache, dass es sich dabei um das Beenden des Prozesses handelt, lässt sich nur aus der Implementierung herauslesen (bei der es sich um nativen Code handelt, nicht dass das einen Unterschied macht).

Wenn Sie die System.exit() in Ihrem Code verwenden (normalerweise ist es am besten, dies zu vermeiden, es sei denn, Sie wollen einen anderen Code als 0 zurückgeben), sollte es in einer Methode stehen, die einen void , main() zum Beispiel. So ist es netter.

Was die Erreichbarkeit betrifft, so ist die Erklärung dieselbe: return ist ein Schlüsselwort der Java-Sprache, so dass der Compiler oder der Parser, den die IDE verwendet, erkennen kann, dass es theoretisch unmöglich ist, dass Code nach der return Anweisung ausgeführt werden. Diese Regeln sind definiert ici .

15voto

Jon Skeet Punkte 1325502

Der Java-Compiler weiß nichts über System.exit . Es ist nur eine Methode, soweit es sie betrifft - das Ende der Anweisung ist also erreichbar.

Sie sagen dass L1 y L2 sind "sichtbar nicht erreichbar", aber das ist sólo denn Sie wissen, was System.exit tut. Die Sprache tut es nicht - während sie tut wissen, was ein return Anweisung, so dass sie weiß, dass L3 wirklich nicht zu erreichen ist.

Ich denke manchmal, dass es nützlich wäre, zu erklären, dass eine Methode nicht nur void aber niemals wird normal beendet - es kehrt nie einfach zurück (obwohl es eine Ausnahme auslösen kann). Der Compiler wäre dann in der Lage, diese Information zu nutzen, um das Ende eines aufrufenden Ausdrucks unerreichbar zu machen und so zu verhindern, dass diese Art von Dingen ein Problem darstellt. Aber das sind nur meine Träume über Sprachdesign - Java nicht und es wäre eine sehr schlechte Idee, wenn der Compiler "wüsste", dass bestimmte JRE-Methoden niemals normal zurückkehren, wenn dieses Konzept nicht direkt in der Sprache ausgedrückt werden kann.

Stattdessen ist der Compiler an die Regeln der Abschnitt 14.21 der JLS , einschließlich:

  • Die erste Anweisung in einem nicht leeren Block, der kein Schalterblock ist, ist erreichbar, wenn der Block erreichbar ist.
  • Jede andere Anweisung S in einem nicht leeren Block, der kein Schalterblock ist, ist erreichbar, wenn die Anweisung vor S normal abgeschlossen werden kann.

...

Eine Ausdrucksanweisung kann normal abgeschlossen werden, wenn sie erreichbar ist.

(Ein Methodenaufruf ist eine Ausdrucksanweisung.)

Dann ab Abschnitt 8.4.7:

Wenn eine Methode so deklariert ist, dass sie einen Rückgabetyp hat, dann tritt ein Kompilierfehler auf, wenn der Körper der Methode normal abgeschlossen werden kann (§14.1).

und in 14.1:

Wenn nicht anders angegeben, wird eine Anweisung normal abgeschlossen, wenn alle von ihr ausgewerteten Ausdrücke und alle von ihr ausgeführten Substatements normal abgeschlossen werden.

Die Aufforderung an System.exit() kann aus Sicht des Compilers normal abgeschlossen werden, was bedeutet, dass der Körper der foo Methode normal abgeschlossen werden kann, was zu dem Fehler führt.

7voto

Andrey Agibalov Punkte 7526

Vom sprachlichen Standpunkt aus gibt es nur 2 Möglichkeiten, dem aktuellen Geltungsbereich zu entkommen: return y throw . Methodenaufrufe werden nie auf die gleiche Weise betrachtet, selbst wenn sie aus der einzigen Codezeile bestehen:

void method() {
  throw new RuntimeException();
}

Mehr noch. Theoretisch kann jeder Methodenaufruf zu RuntimeException geworfen zu werden. In diesem Fall sollte der Compiler wahrscheinlich Warnungen für absolut jeden Methodenaufruf ausgeben, der nicht innerhalb einer try Block:

...
method(); // WARNING: may throw in theory
anotherMethod(); // WARNING: possible unreachable code, also may throw
anotherMethod2(); // WARNING: possible unreachable code, also may throw
// etc
...

Für Ihre Frage ist die Logik dieselbe.

0voto

Wulfram Punkte 3252

Es ist möglich, dass das statische Codeanalysetool nicht berücksichtigt, dass die Anwendung beendet wird.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X