[Java] Verwendung von final in der lokalen Variablendeklaration

Ist final erforderlich, um lokale Variablen zu deklarieren?

Ich benutze final grundsätzlich nicht in meinen eigenen Funktionen. Ich denke, der Grund ist einfach "Ich habe es geschrieben, damit Sie es sehen können." Zum Beispiel hat es die folgende Form.

public static int f(int x) {
  int y = g(x);
  int z = h(y);
  return z;
}

Wenn Sie sich das ansehen, ist es selbstverständlich, dass y und z (und x) nicht neu zugewiesen werden. Und da die von mir definierte Funktion normalerweise einige Zeilen wie diese umfasst, ist das Hinzufügen von final zum Zeitpunkt der Deklaration meines Erachtens überflüssig, daher versuche ich, sie nicht hinzuzufügen.

Ich denke jedoch, dass es in Ordnung ist, einen anderen zu haben. Wenn zum Beispiel die IDE-Einstellungen so eingestellt sind, dass automatisch final hinzugefügt wird, hat dies zumindest keinen Einfluss auf die Anzahl der Typen, und ich denke, dass es sich bald an das Erscheinungsbild gewöhnen wird. Kurz gesagt, in den oben genannten Fällen sind wir nicht so besonders.

Situationen, die final verwenden

Wenn Sie final überhaupt nicht verwenden, ist dies nicht der Fall, und in einigen Fällen kann es auch verwendet werden. Im Folgenden werde ich einen Fall vorstellen, in dem ich final endgültig verwende.

1. Erklärung in einer langen Funktion

Da die obige Funktion von mir selbst definiert wurde, dauerte es nur wenige Zeilen, aber wenn Sie sie im tatsächlichen Geschäft ändern, ist es möglich, Variablen in einer sehr langen Funktion (Hunderte von Zeilen, Tausend Zeilen usw.) zu deklarieren. Innerhalb solcher Funktionen ist es nicht ungewöhnlich, dass zwischen der Variablendeklaration und dem Verwendungsort der Variablen zehn oder Hunderte von Zeilen liegen. Wenn zu diesem Zeitpunkt final zum Zeitpunkt der Deklaration nicht beigefügt ist, müssen alle dazwischen liegenden Zeilen gelesen und der neueste Wert erfasst werden.

Zeilennummer
100      public static int longLongFunc() {
101        String foo = "foo";

~~ weggelassen ~~

           //Sie müssen die 400 Zeilen dazwischen lesen, um den Wert von foo an dieser Stelle zu kennen.
500        String bar = hoge(foo);

・ ・ ・

Alternativ wird der Bereich fortgesetzt, nachdem die Variable verwendet wurde, sodass sich der Wert in den Zeilen darunter möglicherweise nicht erneut ändert.

           //Es kann so wiederverwendet werden(Was ist Initialisierung ...)¡
700        foo = null; //Initialisieren
701        foo = fuga();

・ ・ ・

Natürlich kann es eine Geschichte sein, die durch Codeüberprüfung verhindert werden kann, aber in der realen Welt ist es nicht ungewöhnlich, dass Unternehmen keine solche Kultur haben.

Die oben genannten Fälle können durch Hinzufügen von final bei der Deklaration behandelt werden.

Zeilennummer
100      public static int longLongFunc() {
101        final String foo = "foo";

~~ weggelassen ~~

           //Der Wert von foo hat sich seit seiner Deklaration nicht geändert("foo"Wie es ist)Daher ist es nicht notwendig, die Verarbeitung dazwischen zu erfassen.
500        String bar = hoge(foo);

~~ weggelassen ~~

           //Kann in der folgenden Zeile nicht wiederverwendet werden, da dies zu einem Kompilierungsfehler führt
700        foo = null; //Kompilierungsfehler


・ ・ ・

2. Wenn Sie einen Wert gemäß den Bedingungen einstellen

(19/10/1 Nachschrift / Korrektur) Herr @Kilisame hat in den Kommentaren darauf hingewiesen, und ich habe mein großes Missverständnis herausgefunden, sodass ich eine größere Korrektur vornehme. Lokale Java-Variablen führen unabhängig vom Vorhandensein oder Fehlen von final zu einem Kompilierungsfehler, wenn der Anfangswert nicht nur durch die Deklaration zugewiesen wird, sondern nur im Fall der Deklaration der implizite Anfangswert wie im Feld zugewiesen wird. Ich habe es falsch verstanden. Vielen Dank für den Hinweis, @Kilisame.


Bei der bedingten Verzweigung wird häufig auch final verwendet. Betrachten Sie beispielsweise den folgenden Fall.
String hoge = "";
if (isFoo) {
  hoge = "foo";
} else if (isBar) {
  hoge = "bar";
}

Wenn Sie einfach nicht neu zuweisen möchten, können Sie auch den bedingten Operator (ternären Operator) verwenden, um Folgendes zu schreiben:

String hoge = isFoo ? "foo" : isBar ? "bar" : "";

Es ist nicht unmöglich zu schreiben, aber es ist sicherlich schwer zu sehen, ob sonst gemischt ist, nicht nur wenn-sonst. Grundsätzlich ist es besser, das Verschachteln von bedingten Operatoren zu vermeiden. In einem solchen Fall können Sie auch wie folgt schreiben.

// 19/10/1 Zur Korrektur auskommentieren(Siehe zusätzliche Hinweise)
// final String hoge; //Nur Erklärung

String hoge; //Nur Erklärung
//Ersetzen Sie einen Wert entsprechend der Bedingung
if (isFoo) {
  hoge = "foo";
} else if (isBar) {
  hoge = "bar";
} else {
  hoge = "";
}

Da ~~ final "ein Wert ist, der nur einmal zugewiesen werden kann", kann der Zeitpunkt der Deklaration und Zuweisung selbst unterschiedlich sein. Stattdessen wird ein Kompilierungsfehler angezeigt, wenn Sie keinen Wert festlegen, bevor der Gültigkeitsbereich überschritten wird. Der Vorteil des obigen Schreibens besteht darin, dass Sie die Überwachung von Fällen verhindern können, in denen kein Wert festgelegt ist. Das folgende Beispiel führt beispielsweise zu einem Kompilierungsfehler. ~~

(19/10/1 Nachschrift / Korrektur) Auch wenn es kein Finale gibt, tritt ein Kompilierungsfehler auf, wenn der Anfangswert nicht nur in der Deklaration zugewiesen wird.

// 19/10/1 Zur Korrektur auskommentieren
// final String hoge;

String hoge;
if (isFoo) {
  hoge = "foo";
} else if (isBar) {
  String fuga = getFuga();
  if (!fuga.isEmpty()) {
    hoge = fuga;
  } //Wenn dies falsch ist, wird der Wert nicht festgelegt, was zu einem Kompilierungsfehler führt.
} else {
  hoge = "";
}

Um die Zusammenstellung zu bestehen, müssen alle Fälle wie folgt abgedeckt werden.

// 19/10/1 Zur Korrektur auskommentieren
// final String hoge;

String hoge;
if (isFoo) {
  hoge = "foo";
} else if (isBar) {
  String fuga = getFuga();
  if (!fuga.isEmpty()) {
    hoge = fuga;
  } else {
    hoge = "bar";
  }
} else {
  hoge = "";
}

~~ Entfernen Sie als zusätzliche Ergänzung das letzte des obigen Beispiels, das einen Kompilierungsfehler verursacht, und ersetzen Sie den Anfangswert. ~~

(19/10/1 Nachschrift / Korrektur) Da final entfernt wird, wird nur der Anfangswert ersetzt.

String hoge = "";
if (isFoo) {
  hoge = "foo";
} else if (isBar) {
  String fuga = getFuga();
  if (!fuga.isEmpty()) {
    hoge = fuga;
  } //Wenn dies falsch ist, ist hoge""wie es ist.
}

In diesem Fall wird die Kompilierung selbst bestanden. Dies kann jedoch daran liegen, dass Sie vergessen haben, den Fall zu schreiben, in dem fuga.isEmpty () true ist (natürlich kann dies wie erwartet sein).

String hoge = "";
if (isFoo) {
  hoge = "foo";
} else if (isBar) {
  String fuga = getFuga();
  if (!fuga.isEmpty()) {
    hoge = fuga;
  } else {
    hoge = "bar"; //Vielleicht hatte ich vor, so zu schreiben
  }
}

Diese Art von Fehler ist auch in der Praxis ein häufiger Fehler. Menschen sind Wesen, die Fehler machen. Auf diese Weise ist es sicherer und sicherer, so zu schreiben, dass ein Kompilierungsfehler auftritt, wenn Sie einen Fehler machen, anstatt so zu schreiben, dass die Kompilierung in beiden Fällen von Fehlern erfolgreich ist und nicht. ~~ Wenn Sie vergessen haben, das obige Beispiel zu schreiben, können Sie unerwartete Fehler verhindern, indem Sie final hinzufügen. ~~

(19/10/1 Nachschrift / Korrektur) Die Richtlinie selbst "Wenn Sie einen Fehler machen, sollten Sie einen Kompilierungsfehler erhalten" ändert sich nicht, aber das obige Beispiel ist unangemessen, da es sich nicht auf das Vorhandensein oder Fehlen von final bezieht. In Bezug auf die Vorteile des Hinzufügens von final in solchen Fällen hat @Kilisame im Kommentarbereich darauf hingewiesen, illustriert und erklärt. Bitte beziehen Sie sich darauf.
Zusätzlich zum obigen Beispiel ist es auch gut, die folgende Funktion auszuführen und aufzurufen.

//Ring Hoge, wenn in eine Funktion gemacht= getHoge();Kann geschrieben werden
public static String getHoge() {
  if (isFoo) {
    return "foo";
  } 
  
  if (isBar) {
    String fuga = getFuga();
    if (!fuga.isEmpty()) {
      return fuga;
    } else {
      return "bar";
    }
  }
  return "";
}

Ich möchte, dass Sie darüber nachdenken, ob Sie es von Fall zu Fall zu einer Funktion machen sollen.

Zusammenfassung

Derzeit füge ich nicht allen lokalen Variablen final hinzu, aber ich beabsichtige zu schreiben mit der Absicht, dass "final allen lokalen Variablen hinzugefügt werden kann". Wenn Sie sich des Hintergrunds und des Zwecks des Hinzufügens von final bewusst sind, z. B. "Verhindern unerwarteter Fehler" und "leichtes Reparieren", wird möglicherweise nicht in die falsche Richtung gedreht. Ich denke.

Oder wenn es sich um Teamentwicklung handelt, denke ich, dass die Strategie, im Codierungsstandard das Finale zu erzwingen und nur die Mindestqualität ohne das Bewusstsein des Programmierers sicherzustellen, auch eine Ameise ist.

In diesem Artikel wollte ich nur den Fall vorstellen, dass "es in solchen Fällen bequemer ist, final zu verwenden", nicht "ob final verwendet werden soll oder nicht", damit Sie oder Ihr Team entscheiden, was zu tun ist. Ich hoffe du kannst darüber nachdenken.

Danke, dass Sie bis zum Ende für mich gelesen haben. Wenn Sie Fragen oder Mängel haben, kontaktieren Sie uns bitte im Kommentarbereich oder unter Twitter.

Recommended Posts

[Java] Verwendung von final in der lokalen Variablendeklaration
Java-Variablendeklaration
Informationen zu in Java verwendeten Variablen (lokaler Variablentyp)
Verwenden Sie OpenCV mit Java
Verwenden Sie PreparedStatement in Java
Verwendung von Abstract Class und Interface in Java richtig
Informationen zu Java-Variablendeklarationsanweisungen
Java-Implementierung von Tri-Tree
Deklaration, Initialisierung und Typen von Java-Variablen
[Java] Verwenden Sie nicht "+" im Anhang!
Verwenden Sie zusammengesetzte Schlüssel in Java Maps.
So schreiben Sie eine Java-Variablendeklaration
Liste der in Java 9 hinzugefügten Mitglieder
Wie verwende ich Klassen in Java?
Liste der in Java 9 hinzugefügten Typen
Implementierung einer ähnlichen Funktion in Java
Verwenden Sie Stream in Java?
[Java8] Angemessene Verwendung von Compareable und Comparator unter dem Gesichtspunkt der Mitarbeitersortierung
Implementierung von DBlayer in Java (RDB, MySQL)
Holen Sie sich das Ergebnis von POST in Java
Mehrsprachige Unterstützung für Java Verwendung des Gebietsschemas
Verwenden Sie OpenCV_Contrib (ArUco) mit Java! (Teil 2-Programmierung)
Erstellen Sie Binärdaten variabler Länge in Java
Unterschied zwischen final und Immutable in Java
Verwenden Sie den statischen Initialisierungsblock, um die Liste / den Satz statischer Felder in Java zu initialisieren
[Java] Verwenden Sie kryptografische Technologie mit Standardbibliotheken
Verwenden Sie "Rhino", das JavaScript in Java ausführt
Was war keine faire Verwendung der Java-API-Umleitung unter Android?
[Java] [Maven3] Zusammenfassung der Verwendung von Maven3
Die Geschichte des Schreibens von Java in Emacs
Rolle von JSP in Webanwendungen [Java]
Diskriminierung von Enum in Java 7 und höher
[Java] Warum StringUtils.isEmpty () anstelle von String.isEmpty () verwenden?
Verwenden Sie jenv, um mehrere Java-Versionen zu aktivieren
Die Geschichte des einfachen String-Vergleichs in Java
[Java] Behandlung von Java Beans in der Methodenkette
Die Geschichte eines gewöhnlichen Othello in Java
Über die Idee anonymer Klassen in Java
[Android / Java] Betreiben Sie eine lokale Datenbank in Room
Die Geschichte des Lernens von Java in der ersten Programmierung
[Java] benutze Optional anstelle von if (hoge! = Null) {...}
Spüren Sie den Lauf der Zeit auch in Java
Ändern Sie dynamisch private statische Endfelder in Java
Ein kurzer Überblick über Java, das im Unterricht gelernt wurde
Verwendung von JQuery in Rails 6 js.erb
[JAVA] [Spring] [MyBatis] Verwenden Sie IN () mit SQL Builder
Was mich schon immer an Java Final interessiert hat
Methodenname der Methodenkette in Java Builder + α
[Java] Unterschied zwischen "endgültiger Variable" und "unveränderlichem Objekt"
Importieren Sie Dateien derselben Hierarchie in Java
Initialisierungszeitpunkt der Mitgliedsvariablen mit endgültiger Angabe
Partisierung in Java
Janken in Java
Java-Variablenbereich (Bereich)
Java-Variablenbereich
[Java] [Maven] Vorlage von pom.xml zum Registrieren der JAR-Datei eines Drittanbieters im lokalen Repository