Wann sollte final für Methodenparameter und lokale Variablen verwendet werden?


171

Ich habe einige Referenzen gefunden ( zum Beispiel ), die vorschlagen, finalso viel wie möglich zu verwenden, und ich frage mich, wie wichtig das ist. Dies geschieht hauptsächlich im Zusammenhang mit Methodenparametern und lokalen Variablen, nicht mit endgültigen Methoden oder Klassen. Für Konstanten ist dies offensichtlich sinnvoll.

Einerseits kann der Compiler einige Optimierungen vornehmen und macht die Absicht des Programmierers klarer. Auf der anderen Seite wird die Ausführlichkeit erhöht, und die Optimierungen können trivial sein.

Ist es etwas, an das ich mich erinnern sollte?


Hier ist ein verwandter Beitrag, den Sie sich ansehen sollten: stackoverflow.com/questions/137868/…
mattlant


1
Ich stimme zu, nur weil ich nicht wusste, dass es möglich ist, final als Modifikator für Parameter zu verwenden, bevor ich dies lese. Vielen Dank!
Kip

Antworten:


178

Bessesen von:

  • Endgültige Felder - Wenn Sie Felder als endgültig markieren, müssen sie bis zum Ende der Konstruktion festgelegt werden, sodass diese Feldreferenz unveränderlich ist. Dies ermöglicht die sichere Veröffentlichung von Feldern und vermeidet die Notwendigkeit einer Synchronisation bei späteren Lesevorgängen. (Beachten Sie, dass für eine Objektreferenz nur die Feldreferenz unveränderlich ist - Dinge, auf die sich die Objektreferenz bezieht, können sich noch ändern und dies wirkt sich auf die Unveränderlichkeit aus.)
  • Endgültige statische Felder - Obwohl ich jetzt in vielen Fällen, in denen ich statische endgültige Felder verwendet habe, Aufzählungen verwende.

Betrachten Sie, aber verwenden Sie mit Bedacht:

  • Letzte Klassen - Framework / API-Design ist der einzige Fall, in dem ich es betrachte.
  • Endgültige Methoden - Grundsätzlich gleich wie Abschlussklassen. Wenn Sie Muster für Vorlagenmethoden wie "Verrückt" und "Endgültiges Markieren" verwenden, verlassen Sie sich wahrscheinlich zu sehr auf die Vererbung und nicht genug auf die Delegierung.

Ignorieren, es sei denn, Sie fühlen sich anal:

  • Methodenparameter und lokale Variablen - Ich mache das selten, weil ich faul bin und finde, dass es den Code unübersichtlich macht. Ich gebe voll und ganz zu, dass das Markieren von Parametern und lokalen Variablen, die ich nicht ändern werde, "richtiger" ist. Ich wünschte, es wäre die Standardeinstellung. Aber das ist es nicht und ich finde den Code schwieriger zu verstehen, wenn das Finale vorbei ist. Wenn ich in einem anderen Code bin, werde ich ihn nicht herausziehen, aber wenn ich neuen Code schreibe, werde ich ihn nicht einfügen. Eine Ausnahme ist der Fall, in dem Sie etwas Endgültiges markieren müssen, damit Sie darauf zugreifen können es aus einer anonymen inneren Klasse.

  • Bearbeiten: Beachten Sie, dass ein Anwendungsfall, in dem endgültige lokale Variablen tatsächlich sehr nützlich sind, wie von @ adam-gent erwähnt, darin besteht, dass der Variable in den Zweigen if/ ein Wert zugewiesen wird else.


8
Joshua Bloch argumentiert, dass alle Klassen als endgültig definiert werden sollten, es sei denn, sie sind für die Vererbung ausgelegt. Ich stimme ihm zu; Ich füge jeder Klasse, die eine Schnittstelle implementiert, final hinzu (um Unit-Tests erstellen zu können). Markieren Sie außerdem alle geschützten / Klassenmethoden als endgültig, die nicht überschrieben werden.
Rmaruszewski

61
Bei allem Respekt vor Josh Bloch (und das ist eine beträchtliche Menge) stimme ich dem allgemeinen Fall nicht zu. Sperren Sie beim Erstellen einer API die Dinge. Es ist Zeitverschwendung, in Ihrem eigenen Code Mauern zu errichten, die Sie später abreißen müssen.
Alex Miller

9
Es ist definitiv keine "Zeitverschwendung", vor allem, weil es überhaupt keine Zeit kostet ... In einer Anwendung mache ich normalerweise finalstandardmäßig fast alle Klassen . Möglicherweise bemerken Sie die Vorteile nur, wenn Sie eine wirklich moderne Java-IDE verwenden (dh IDEA).
Rogério

9
IDEA hat (sofort einsatzbereit) Hunderte von Code-Inspektionen, von denen einige nicht verwendeten / unnötigen Code in finalKlassen / Methoden erkennen können. Wenn beispielsweise eine endgültige Methode deklariert, eine aktivierte Ausnahme auszulösen, diese jedoch nie auslöst, teilt Ihnen IDEA dies mit, und Sie können die Ausnahme aus der throwsKlausel entfernen . Manchmal finden Sie auch ganze Methoden, die nicht verwendet werden. Dies ist erkennbar, wenn sie nicht überschrieben werden können.
Rogério

8
@rmaruszewski Das Markieren von Klassen als endgültig verhindert, dass die meisten spöttischen Frameworks sie verspotten können, wodurch das Testen von Code schwieriger wird. Ich würde ein Klassenfinale nur machen, wenn es von entscheidender Bedeutung wäre, dass es nicht verlängert wird.
Mike Rylander

44

Ist es etwas, an das ich mich erinnern sollte?

Nein, wenn Sie Eclipse verwenden, da Sie eine Speicheraktion so konfigurieren können, dass diese endgültigen Modifikatoren automatisch für Sie hinzugefügt werden . Dann erhalten Sie die Vorteile für weniger Aufwand.


3
Toller Tipp mit der Save Action, wusste nichts davon.
Vernunft

1
Ich denke hauptsächlich an den Vorteil, dass final den Code vor Fehlern schützt, indem er versehentlich der falschen Variablen zugewiesen wird, und nicht an Optimierungen, die möglicherweise auftreten oder nicht.
Peter Hilton

4
Ist das wirklich ein Problem für dich? Wie oft hatten Sie tatsächlich einen Fehler, der daraus resultierte?
Alex Miller

1
+1 für nützliche Tipps in Eclipse. Ich denke, wir sollten final so oft wie möglich verwenden, um Fehler zu vermeiden.
Smaragdhieu

Können Sie dies auch in IntelliJ tun?
Koray Tugay

15

Die Entwicklungszeitvorteile von "final" sind mindestens so bedeutend wie die Laufzeitvorteile. Es informiert zukünftige Redakteure des Codes über Ihre Absichten.

Das Markieren einer Klasse als "endgültig" zeigt an, dass Sie sich beim Entwerfen oder Implementieren der Klasse nicht bemüht haben, die Erweiterung ordnungsgemäß zu handhaben. Wenn die Leser Änderungen an der Klasse vornehmen können und den Modifikator "final" entfernen möchten, können sie dies auf eigenes Risiko tun. Es liegt an ihnen, sicherzustellen, dass die Klasse die Erweiterung gut handhabt.

Das Markieren einer Variablen "final" (und das Zuweisen im Konstruktor) ist bei der Abhängigkeitsinjektion hilfreich. Es zeigt die "Kollaborateur" -Natur der Variablen an.

Das Markieren einer Methode als "final" ist in abstrakten Klassen nützlich. Es wird klar umrissen, wo sich die Erweiterungspunkte befinden.


11

Ich benutze die finalganze Zeit, um Java ausdrucksbasierter zu machen. Siehe Javas Bedingungen ( if,else,switch) sind nicht ausdrucksbasiert, was ich immer gehasst habe, besonders wenn Sie an funktionale Programmierung gewöhnt sind (dh ML, Scala oder Lisp).

Daher sollten Sie versuchen, (IMHO) immer endgültige Variablen zu verwenden, wenn Sie Bedingungen verwenden.

Lassen Sie mich Ihnen ein Beispiel geben:

    final String name;
    switch(pluginType) {
        case CANDIDATE_EXPORT:
            name = "Candidate Stuff";
            break;
        case JOB_POSTING_IMPORT:
            name = "Blah";
            break;
        default:
            throw new IllegalStateException();
    }

Wenn Sie eine weitere caseAnweisung hinzufügen und nicht festlegen, nameschlägt der Compiler fehl. Der Compiler schlägt auch fehl, wenn Sie nicht in jedem Fall brechen (dass Sie die Variable festlegen). Auf diese Weise können Sie Java den letAusdrücken von Lisp sehr ähnlich machen und es so gestalten, dass Ihr Code nicht massiv eingerückt wird (aufgrund von lexikalischen Gültigkeitsbereichsvariablen).

Und wie @Recurse feststellte (aber anscheinend -1 me), können Sie das Vorhergehende tun String name final, ohne den Compilerfehler zu erhalten (von dem ich nie gesagt habe, dass Sie es nicht können), aber Sie könnten den Compilerfehler leicht verschwinden lassen, indem Sie den Namen nach dem Wechsel einstellen Anweisung, die die Ausdruckssemantik wegwirft oder schlimmer noch vergisst, breakdass Sie keinen Fehler verursachen können (trotz der Aussagen von @Recurse), ohne Folgendes zu verwenden final:

    String name;
    switch(pluginType) {
        case CANDIDATE_EXPORT:
            name = "Candidate Stuff";
            //break; whoops forgot break.. 
            //this will cause a compile error for final ;P @Recurse
        case JOB_POSTING_IMPORT:
            name = "Blah";
            break;
    }
    // code, code, code
    // Below is not possible with final
    name = "Whoops bug";

Aufgrund des Namens der Fehlereinstellung (abgesehen davon, breakdass ich auch einen anderen Fehler vergessen habe ) kann ich dies jetzt versehentlich tun:

    String name;
    switch(pluginType) {
        case CANDIDATE_EXPORT:
            name = "Candidate Stuff";
            break;
        //should have handled all the cases for pluginType
    }
    // code, code, code
    // Below is not possible with final
    name = "Whoops bug";

Die letzte Variable erzwingt eine einzelne Bewertung des Namens. Ähnlich wie eine Funktion mit einem Rückgabewert immer einen Wert zurückgeben muss (Ausnahmen ignorieren), muss der Namenswechselblock den Namen auflösen und somit an den Schalterblock gebunden sein, der das Refactoring von Codeabschnitten erleichtert (dh Eclipe-Refactor: Extraktionsmethode). .

Das obige in OCaml:

type plugin = CandidateExport | JobPostingImport

let p = CandidateExport

let name = match p with
    | CandidateExport -> "Candidate Stuff"
    | JobPostingImport -> "Blah" ;;

Das match ... with ...wertet wie eine Funktion dh Ausdruck aus. Beachten Sie, wie es mit unserer switch-Anweisung aussieht.

Hier ist ein Beispiel in Schema (Schläger oder Huhn):

(define name 
    (match b
      ['CandidateExport "Candidate Stuff"]
      ['JobPostingImport "Blah"]))

1
Abgesehen davon, dass der Java-Compiler Ihnen bereits einen Fehler "Name möglicherweise nicht initialisiert" gibt und sich weigert, mit oder ohne das Finale zu kompilieren.
Recurse

4
Ja, aber ohne das Finale können Sie es jederzeit zurücksetzen. Ich habe dies tatsächlich gesehen, als ein Entwickler ein else if (...)in ein verwandelte if(...)und so die Variable zurücksetzte. Ich habe ihm gezeigt, dass dies mit einer endgültigen Variablen niemals passiert wäre. Grundsätzlich finalzwingt Sie, die Variable einmal und nur einmal zuzuweisen ... also: P
Adam Gent

9

Ich habe festgestellt, dass das Markieren von Methodenparametern und Einheimischen als finalRefactoring-Hilfe nützlich ist, wenn die betreffende Methode mehrere Seiten lang ein unverständliches Durcheinander ist. Streuen Sie finalgroßzügig, um zu sehen, welche Fehler der Compiler (oder Ihre IDE) der endgültigen Variablen nicht zuweisen kann, und Sie werden möglicherweise feststellen, warum die Variable "data" null wird, obwohl mehrere (veraltete) Kommentare dies schwören nicht passieren.

Anschließend können Sie einige der Fehler beheben, indem Sie die wiederverwendeten Variablen durch neue Variablen ersetzen, die näher am Verwendungsort deklariert wurden. Dann können Sie ganze Teile der Methode in Klammern einschließen, und plötzlich sind Sie einen IDE-Tastendruck von "Extract Method" entfernt, und Ihr Monster ist gerade noch verständlicher geworden.

Wenn Ihre Methode nicht bereits ein nicht wartbares Wrack ist, könnte es sinnvoll sein, Dinge endgültig zu machen, um die Leute davon abzuhalten, sie in das Wrack zu verwandeln. Wenn es sich jedoch um eine kurze Methode handelt (siehe: nicht nicht wartbar), besteht die Gefahr, dass Sie viel Ausführlichkeit hinzufügen. Insbesondere Java-Funktionssignaturen sind schwer genug, um in 80 Zeichen zu passen, ohne sechs weitere pro Argument hinzuzufügen!


1
Sehr gültiger letzter Punkt, obwohl ich vor langer Zeit das Limit von 80 Zeichen aufgegeben habe, da sich die Bildschirmauflösung in den letzten 10 Jahren etwas geändert hat. Ich kann problemlos eine 300-Zeichen-Zeile auf meinem Bildschirm anbringen, ohne zu scrollen. Trotzdem ist die Lesbarkeit natürlich ohne die finalvor jedem Parameter besser .
Brimborium

8

Nun, das hängt alles von Ihrem Stil ab. Wenn Sie das Finale sehen möchten, wenn Sie die Variable nicht ändern, verwenden Sie es. Wenn Sie es nicht mögen, dann lassen Sie es weg.

Ich persönlich mag so wenig Ausführlichkeit wie möglich, daher vermeide ich es, zusätzliche Schlüsselwörter zu verwenden, die nicht wirklich notwendig sind.

Ich bevorzuge jedoch dynamische Sprachen, daher ist es wahrscheinlich keine Überraschung, dass ich Ausführlichkeit vermeiden möchte.

Also würde ich sagen, wählen Sie einfach die Richtung, in die Sie sich neigen, und gehen Sie einfach damit um (versuchen Sie auf jeden Fall, konsequent zu sein).


Als Randnotiz habe ich an Projekten gearbeitet, die ein solches Muster verwenden und nicht verwenden, und ich habe keinen Unterschied in der Anzahl der Fehler oder Fehler gesehen ... Ich denke nicht, dass es ein Muster ist, das enorm sein wird Verbessern Sie die Anzahl Ihrer Fehler oder ähnliches, aber es ist wieder Stil. Wenn Sie die Absicht zum Ausdruck bringen möchten, dass Sie ihn nicht ändern, verwenden Sie ihn.


6

Bei Parametern ist es hilfreich, eine versehentliche Änderung des Parameterwerts zu vermeiden und einen subtilen Fehler einzuführen. Ich ignoriere diese Empfehlung, aber nachdem ich ungefähr 4 Stunden verbracht habe. In einer schrecklichen Methode (mit Hunderten von Codezeilen und mehreren Fors, verschachtelten Ifs und allen möglichen schlechten Praktiken) würde ich Ihnen empfehlen, dies zu tun.

 public int processSomethingCritical( final int x, final int y ){
 // hundreds of lines here 
     // for loop here...
         int x2 = 0;
        x++; // bug aarrgg...
 // hundreds of lines there
 // if( x == 0 ) { ...

 }

Natürlich würde dies in einer perfekten Welt nicht passieren, aber ... nun ... manchmal muss man anderen Code unterstützen. :((


2
Diese Methode hat schwerwiegendere Probleme als das Fehlen von final. Es ist ziemlich ungewöhnlich, wenn auch nicht unmöglich, dass es einen guten Grund dafür gibt, dass eine Methode so überladen ist, dass solche Fehler auftreten. Ein kleiner Gedanke in Variablennamen würde einen großen Beitrag zu solchen Unfällen leisten.
Ykaganovich

2
Wenn Sie "Hunderte von Codezeilen" in einer einzelnen Methode haben, möchten Sie diese möglicherweise in mehrere kleinere Methoden aufteilen.
Steve Kuo

5

Wenn Sie eine Anwendung schreiben, bei der jemand den Code beispielsweise nach 1 Jahr lesen muss, verwenden Sie die Variable final on, die nicht ständig geändert werden sollte. Auf diese Weise wird Ihr Code "selbstdokumentierender" und Sie verringern auch die Wahrscheinlichkeit für andere Entwickler, alberne Dinge wie die Verwendung einer lokalen Konstante als lokale temporäre Variable zu tun.

Wenn Sie einen Wegwerfcode schreiben, müssen Sie nicht alle Konstanten identifizieren und endgültig machen.


4

Ich werde final so viel wie möglich verwenden. Dies wird angezeigt, wenn Sie das Feld unbeabsichtigt ändern. Ich habe auch die Methodenparameter auf final gesetzt. Dabei habe ich mehrere Fehler in Code entdeckt, den ich übernommen habe, als sie versuchten, einen Parameter zu setzen, der vergisst, dass Java als Wert übergeben wird.


2

Aus der Frage geht nicht hervor, ob dies offensichtlich ist, aber das Festlegen eines Methodenparameters wirkt sich nur auf den Hauptteil der Methode aus. Es werden dem Aufrufer KEINE interessanten Informationen über die Absichten der Methode übermittelt. Das übergebene Objekt kann weiterhin innerhalb der Methode mutiert werden (Finale sind keine Konstanten), und der Bereich der Variablen liegt innerhalb der Methode.

Um Ihre genaue Frage zu beantworten, würde ich mir nicht die Mühe machen, eine Instanz oder eine lokale Variable (einschließlich Methodenparameter) endgültig zu machen, es sei denn, der Code erfordert dies (z. B. die Variable wird von einer inneren Klasse referenziert) oder eine wirklich komplizierte Logik zu klären.

Zum Beispiel würde ich Variablen endgültig machen, wenn sie logisch konstant sind.


2

Es gibt viele Verwendungszwecke für die Variable final. Hier sind nur einige

Endkonstanten

 public static class CircleToolsBetter {
     public final static double PI = 3.141;
        public double getCircleArea(final double radius) {
          return (Math.pow(radius, 2) * PI);
        }
    }

Dies kann dann für andere Teile Ihres Codes verwendet werden oder von anderen Klassen aufgerufen werden. Wenn Sie den Wert jemals ändern würden, müssten Sie sie nicht einzeln ändern.

Letzte Variablen

public static String someMethod(final String environmentKey) {
    final String key = "env." + environmentKey;
    System.out.println("Key is: " + key);
    return (System.getProperty(key));

  }

}

In dieser Klasse erstellen Sie eine endgültige Variable mit Gültigkeitsbereich, die dem Parameter environmentKey ein Präfix hinzufügt. In diesem Fall ist die endgültige Variable nur innerhalb des Ausführungsbereichs endgültig, der bei jeder Ausführung der Methode unterschiedlich ist. Bei jeder Eingabe der Methode wird das Finale rekonstruiert. Sobald es erstellt wurde, kann es im Rahmen der Methodenausführung nicht mehr geändert werden. Auf diese Weise können Sie eine Variable in einer Methode für die Dauer der Methode festlegen. siehe unten:

public class FinalVariables {


  public final static void main(final String[] args) {
    System.out.println("Note how the key variable is changed.");
    someMethod("JAVA_HOME");
    someMethod("ANT_HOME");
  }
}

Endkonstanten

public double equation2Better(final double inputValue) {
    final double K = 1.414;
    final double X = 45.0;

double result = (((Math.pow(inputValue, 3.0d) * K) + X) * M);
double powInputValue = 0;         
if (result > 360) {
  powInputValue = X * Math.sin(result); 
} else {
  inputValue = K * Math.sin(result);   // <= Compiler error   
}

Diese sind besonders nützlich, wenn Sie wirklich lange Codezeilen haben und sie einen Compilerfehler erzeugen, sodass Sie nicht auf Logik- / Geschäftsfehler stoßen, wenn jemand versehentlich Variablen ändert, die nicht geändert werden sollten.

Endgültige Sammlungen

In einem anderen Fall, wenn es sich um Sammlungen handelt, müssen Sie sie als nicht modifizierbar festlegen.

 public final static Set VALID_COLORS; 
    static {
      Set temp = new HashSet( );
      temp.add(Color.red);
      temp.add(Color.orange);
      temp.add(Color.yellow);
      temp.add(Color.green);
      temp.add(Color.blue);
      temp.add(Color.decode("#4B0082")); // indigo
      temp.add(Color.decode("#8A2BE2")); // violet
      VALID_COLORS = Collections.unmodifiableSet(temp);
    }

Andernfalls, wenn Sie es nicht als nicht änderbar festlegen:

Set colors = Rainbow.VALID_COLORS;
colors.add(Color.black); // <= logic error but allowed by compiler

Final Classes und Final Methods können nicht erweitert bzw. überschrieben werden.

BEARBEITEN: UM DAS ENDGÜLTIGE KLASSENPROBLEM IN BEZUG AUF DIE ENKAPSULATION ZU BEHEBEN:

Es gibt zwei Möglichkeiten, ein Klassenfinale zu erreichen. Das erste besteht darin, das Schlüsselwort final in der Klassendeklaration zu verwenden:

public final class SomeClass {
  //  . . . Class contents
}

Die zweite Möglichkeit, ein Klassenfinale zu erreichen, besteht darin, alle Konstruktoren als privat zu deklarieren:

public class SomeClass {
  public final static SOME_INSTANCE = new SomeClass(5);
  private SomeClass(final int value) {
  }

Wenn Sie es als endgültig markieren, sparen Sie sich die Mühe, wenn Sie feststellen, dass es sich tatsächlich um ein Finale handelt, um einen Blick auf diese Testklasse zu werfen. sieht auf den ersten Blick öffentlich aus.

public class Test{
  private Test(Class beanClass, Class stopClass, int flags)
    throws Exception{
    //  . . . snip . . . 
  }
}

Da der einzige Konstruktor der Klasse privat ist, ist es leider unmöglich, diese Klasse zu erweitern. Im Fall der Testklasse gibt es keinen Grund, warum die Klasse endgültig sein sollte. Die Testklasse ist ein gutes Beispiel dafür, wie implizite Abschlussklassen Probleme verursachen können.

Sie sollten es also als endgültig markieren, wenn Sie eine Klasse implizit endgültig machen, indem Sie ihren Konstruktor privat machen.


1

Wie Sie bereits erwähnt haben, ein Kompromiss, aber ich bevorzuge die explizite Verwendung von etwas gegenüber der impliziten Verwendung. Dies wird dazu beitragen, einige Unklarheiten für zukünftige Codeverwalter zu beseitigen - selbst wenn es nur Sie sind.


1

Wenn Sie innere (anonyme) Klassen haben und die Methode auf die Variable der enthaltenen Methode zugreifen muss, müssen Sie diese Variable als endgültig haben.

Davon abgesehen ist das, was Sie gesagt haben, richtig.


Jetzt bietet Java 8 Flexibilität mit effektiven endgültigen Variablen.
Ravindra Babu

0

Verwenden Sie das finalSchlüsselwort für eine Variable, wenn Sie diese Variable als erstellenimmutable

Durch das Deklarieren der Variablen als endgültig können Entwickler mögliche Änderungsprobleme von Variablen in einer Umgebung mit mehreren Multithreads ausschließen.

Mit Java 8 haben wir ein weiteres Konzept namens " effectively final variable". Eine nicht endgültige Variable kann als endgültige Variable angehoben werden.

Lokale Variablen, auf die aus einem Lambda-Ausdruck verwiesen wird, müssen endgültig oder effektiv endgültig sein

Eine Variable gilt als effektiv endgültig, wenn sie nach der Initialisierung im lokalen Block nicht geändert wird. Dies bedeutet, dass Sie die lokale Variable jetzt ohne das Schlüsselwort final in einer anonymen Klasse oder einem Lambda-Ausdruck verwenden können, vorausgesetzt, sie müssen effektiv final sein.

Bis Java 7 können Sie keine nicht endgültige lokale Variable in einer anonymen Klasse verwenden, aber von Java 8 aus

Schauen Sie sich diesen Artikel an


-1

Zunächst wird das letzte Schlüsselwort verwendet, um eine Variable konstant zu machen. Konstante bedeutet, dass es sich nicht ändert. Beispielsweise:

final int CM_PER_INCH = 2.54;

Sie würden die Variable final deklarieren, da sich ein Zentimeter pro Zoll nicht ändert.

Wenn Sie versuchen, einen Endwert zu überschreiben, wurde die Variable zuerst deklariert. Beispielsweise:

final String helloworld = "Hello World";
helloworld = "A String"; //helloworld still equals "Hello World"

Es gibt einen Kompilierungsfehler, der ungefähr so ​​aussieht:

local variable is accessed from inner class, must be declared final

Wenn Ihre Variable nicht als endgültig deklariert werden kann oder wenn Sie sie nicht als endgültig deklarieren möchten, versuchen Sie Folgendes:

final String[] helloworld = new String[1];
helloworld[0] = "Hello World!";
System.out.println(helloworld[0]);
helloworld[0] = "A String";
System.out.println(helloworld[0]);

Dies wird gedruckt:

Hello World!
A String
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.