Endgültige Variablenzuweisung mit try/catch

Lesezeit: 3 Minuten

Benutzer-Avatar
dtech

Weil ich glaube, dass es eine gute Programmierpraxis ist, mache ich alle meine (lokalen oder Instanz-) Variablen final wenn sie nur einmal geschrieben werden sollen.

Ich stelle jedoch fest, dass Sie diese Variable nicht endgültig machen können, wenn eine Variablenzuweisung eine Ausnahme auslösen kann:

final int x;
try {
    x = Integer.parseInt("someinput");
}
catch(NumberFormatException e) {
    x = 42;  // Compiler error: The final local variable x may already have been assigned
}

Gibt es eine Möglichkeit, dies zu tun, ohne auf eine temporäre Variable zurückzugreifen? (oder ist dies nicht der richtige Ort für einen letzten Modifikator?)

  • Ich bezweifle, dass Sie dies ohne eine temporäre Variable tun können.

    – NPE

    28. November 2012 um 11:35 Uhr

  • final int x = makeX(); bestimmt. (try-catch in Funktion)

    – Joop Eggen

    28. November 2012 um 11:36 Uhr


  • Schockierend, dass das JDK immer noch keine hat tryParse.

    – TJ Crowder

    28. November 2012 um 11:41 Uhr


  • Um es ganz klar zu sagen, der Compiler-Fehler ist falsch, oder? Es gibt keinen Umstand, unter dem x könnte im gegebenen Beispiel doppelt vergeben werden.

    – jaco0646

    22. Oktober 2014 um 19:41 Uhr

  • @ jaco0646, es verlangt dem Compiler viel ab, das im Allgemeinen zu bekommen, wenn der try-Block mehrere Zeilen enthält, in denen die Ausnahme auftreten könnte. Es wäre jedoch schön, für diesen Zweck einen Ausnahmefall zu haben, der erkennt, wann die Zuweisung die letzte Anweisung im try ist.

    – Joshua Goldberg

    10. Juni 2016 um 17:26 Uhr

Benutzer-Avatar
NPE

Eine Möglichkeit, dies zu tun, ist die Einführung eines (nichtfinal) temporäre Variable, aber Sie sagten, Sie wollten das nicht.

Eine andere Möglichkeit besteht darin, beide Zweige des Codes in eine Funktion zu verschieben:

final int x = getValue();

private int getValue() {
  try {
    return Integer.parseInt("someinput");
  }
  catch(NumberFormatException e) {
    return 42;
  }
}

Ob dies praktikabel ist oder nicht, hängt vom genauen Anwendungsfall ab.

Alles in allem solange x eine lokale Variable mit geeignetem Geltungsbereich ist, könnte der praktischste allgemeine Ansatz darin bestehen, sie nichtfinal.

Wenn andererseits x eine Mitgliedsvariable ist, wäre mein Rat, eine Nicht-final temporär während der Initialisierung:

public class C {
  private final int x;
  public C() {
    int x_val;
    try {
      x_val = Integer.parseInt("someinput");
    }
    catch(NumberFormatException e) {
      x_val = 42;
    }
    this.x = x_val;
  }
}

  • Für einen lokalen Geltungsbereich stimme ich Ihnen zu, dies tritt jedoch am häufigsten bei Instanzvariablen auf.

    – dtech

    28. November 2012 um 11:45 Uhr

  • Ich denke, es könnte einen Fehler widerspiegeln, der keinen statischen Verweis auf die nicht statische Methode getValue() erstellen kann. Wir nehmen also an, dass wir die statische Funktion verwenden

    – gks

    28. November 2012 um 11:45 Uhr

  • Wenn this.x ein Objekttyp wie Integer ist, dann brauchen Sie (leider) etwas mehr. Wenn Sie x_val nicht deklariert lassen, beschwert sich der Compiler, dass er möglicherweise nicht initialisiert wurde. Wenn der Fallback für den Catch-Block null ist, müssen Sie auf null vorinitialisieren und entweder aus Gründen der Übersichtlichkeit null im Catch redundant zuweisen (das ist meine Präferenz) oder einen leeren Catch haben.

    – Joshua Goldberg

    10. Juni 2016 um 17:37 Uhr

  • Was @JoshuaGoldberg sagt, gilt sogar für primitive Typen. Wir haben exakt das gleiche Muster von Code, wo das Mitglied in der Rolle von this.x ist ein Primitiv boolean, ebenso wie die lokale Variable. Selbst mit Java 9 erhalten wir „x_val

    > möglicherweise nicht initialisiert”. Das Fehlen einer Kontrollflussanalyse für diese Situation ist frustrierend, lässt sich aber leicht umgehen.

    – Ti Strga

    15. November 2018 um 17:03 Uhr

Nein, es ist nicht der richtige Ort, stellen Sie sich vor, Sie haben mehr als 1 Statement in Ihrem Try- und Catch-Block, das erste sagt: x = 42. Nach einigen anderen Statements schlägt der Try-Block fehl und es geht zum Catch-Block, wo Ihr Sagen Sie x = 30. Jetzt haben Sie x zweimal definiert.

  • Der Compiler ist intelligent genug, um zu wissen, welche Anweisungen welche Ausnahmen auslösen. Es ist möglicherweise nicht in allen Fällen möglich, aber genau wie der Compiler Sie in einigen Fällen über toten Code usw. informieren kann, sollte er in der Lage sein, herauszufinden, ob final funktionieren würde.

    – Stefan

    18. Februar 2014 um 17:43 Uhr

  • Um zu unterstützen, was @Stefan gesagt hat, kann Clang dies beim Kompilieren von Swift herausfinden.

    – Franklin Yu

    29. April 2016 um 2:25 Uhr

1235770cookie-checkEndgültige Variablenzuweisung mit try/catch

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy