Wie funktioniert das Schlüsselwort "final" von Java?

vish234

Mitglied
In Java verwenden wir das Schlüsselwort final mit Variablen, um anzugeben, dass ihre Werte nicht geändert werden sollen. Ich stelle jedoch fest, dass Sie den Wert in den Methoden der Klasse bearbeiten können. Wenn die Variable statisch ist, ist dies ein weiterer Kompilierungsfehler.
Der Code lautet wie folgt:
Java:
import java.util.ArrayList;
import java.util.List;

class Test {
  private final List foo;

  public Test()
  {
      foo = new ArrayList();
      foo.add("foo"); // Modification-1
  }
  public static void main(String[] args)
  {
      Test t = new Test();
      t.foo.add("bar"); // Modification-2
      System.out.println("print - " + t.foo);
  }
}
Der obige Code ist fehlerfrei. Machen Sie nun die Variable statisch:
Code:
private static final List foo;
Es ist jetzt ein Kompilierungsfehler. Wie funktioniert dieses Finale in der Praxis?
Diese Seite legt nahe, dass private statische Variablen akzeptabel sind, da sie über statische Methoden innerhalb der Klasse verfügbar sind, in der sie deklariert sind. Eine statische Variable ist eine, die nur einmal existiert und nicht an eine Klasseninstanz gebunden ist. Ist das korrekt? Könnte mir bitte jemand helfen?
 

KonradN

Super-Moderator
Mitarbeiter
Also bitte immer genau die Fehlermeldung bringen! Wenn du die Variable static machst, dann muss diese auch initialisiert werden. Und das tust Du nicht bzw, tust es an einer falschen Stelle!

final bedeutet, dass eine Variable nicht mehr geändert werden kann. Der Wert in der Variable ist also unveränderbar. Und die Variable muss initialisiert werden. Bei einer nicht statischen Variable entweder direkt bei der Deklaration final List<String> list = new AraryList<>(); oder im Konstruktor.
Bei einer statischen Variable direkt bei der Deklaration.

Und da nur der Wert in der Variable festgelegt ist, kannst Du natürlich Dinge in einer Instanz anpassen. Also in Deinem Fall: Du fügst DInge zu der List hinzu.

In der Variable ist die Referenz zu der Liste gespeichert. Das ist also wie eine Karte, auf der eine Adresse steht. Nur weil Du die Karte laminierst, damit niemand die Adresse ändern kann, kann das Haus dennoch abbrennen, Gegenstände in das Haus getragen oder heraus getragen werden, oder oder oder ... Nur die Adresse auf genau deiner Karte ist unveränderbar!
 

no-cgpt

Mitglied
@vish234 Du suchst in diesem Fall nach:

Java:
import java.util.List;

public class UKlasse {
    private final List ufoo = List.copyOf(List.of(1, 2, 3));
    private final List ufoo2;

    public UKlasse(List foo2) {
        this.ufoo2 = List.copyOf(foo2);

    }
}

Elemente der Liste können in diesem Fall nicht geändert werden. Aber das ist noch nicht alles ... Du musst zusätzlich sicherstellen, dass die Liste keine Elemente enthalten darf, deren Inhalt geändert werden könnte; diese müssen also auch immutable sein ...

Siehe auch:


Leider ist es etwas "unschön", dass es keine extra Klasse in Java dafür gibt.
 

Oneixee5

Top Contributor
Was du wahrscheinlich erreichen willst ist eine unveränderliche Liste:
Java:
        ArrayList<Character> list = new ArrayList<>();
        ...
        List<Character> immutablelist = Collections.unmodifiableList(list);
        immutablelist.add('A');

immutablelist.add('Z'); // !!!
List.of(1, 2, 3) erzeugt auch eine unveränderliche Liste.
 
Zuletzt bearbeitet:

White_Fox

Top Contributor
Ich hatte das jetzt so verstanden, daß er wissen will wie final funktioniert.

final sorgt dafür, das hast du schon ganz richtig erkannt, daß eine Variable nicht mehr neu beschrieben werden kann. Einen primitiven Datentyp kannst du damit nicht mehr ändern.

Wenn du eine Instanzvariable als final deklarierst, kannst diese nicht mehr ändern. In deinem Fall kannst du deine ArrayList nicht mehr durch eine andere ersetzen, aber natürlich kannst du mit dem Objekt noch ganz normal arbeiten und das bedeutet für eine ArrayList eben auch, neue Elemente hinzuzufügen oder vorhandene zu entfernen. Wenn final das unterbinden würde, hättest du einen ziemlichen Konflikt: Du beschreibst in deiner Klasse ein Verhalten eines Objekts, aber wenn final so funktionieren würde wie du es vermutest, würde diese Beschreibung wieder annulliert. Du würdest eine Verhaltensänderung von außerhalb der Klasse erzwingen, die der Autor der Klasse nicht im Sinn hatte. Und genau das soll ja nicht sein, wenn du eine Klasse verwendest (d.h. mit new ein Objekt vom Klassentyp instanziierst), dann sollst du dich gerade NICHT mit deren Innereien befassen.
Diese Sichtbarkeitsmodifizierer sind genau dafür da, die Innereien einer Klasse vor dir zu verbergen, aber genau das würdest du unterlaufen wenn du von außen einfach mit final das Verhalten der Klasse ändern könntest.

Eine andere Betrachtungsweise: In Java arbeitet man nicht mit Objekten selbst, sondern mit Objektreferenzen. Deshalb kannst du z.B. ein und dasselbe Objekt in zwei verschiedenen Instanzvariablen halten. Beispiel:
Java:
public class ReferencesInJavaDemo{
    class SomethingStrange{
        int theInteger;
        
        public setTheInteger(int newIntegerValue){this.theInteger = newIntegerValue;}
        public int getTheInteger(){return theInteger;}
    }
    
    public int main(String[] args){
        //Instanziere ein neues Objekt vom Typ SomethingStrange, und erhalte eine Referenz dieses neuen Objekts.
        ref1 = new SomethingStrange();
        //Kopiere diese Referenz nun in eine zweite Instanzvariable.
        ref2 = ref1;
        
        //Über ref1 schreiben wir einfach mal etwas in das Objekt rein.
        ref1.setTheInteger(3);
        //Und über ref2 schauen wir in das Objekt rein und werden feststellen, daß genau das darin steht, was wir über ref1 reingeschrieben haben.
        System.out.println("TheInteger in ref2: " + ref2.getTheInteger());
        
        //Und nun prüfen wir, ob das auch ein zweites Mal funktioniert. Wir überschrieben die erste Ändernung...
        ref1.setTheInteger(42);
        //...und schauen wieder über ref2 nach, was in dem Objekt steht:
        System.out.println("TheInteger in ref2 im zweiten Durchlauf: " + ref2.getTheInteger());
        
        //Das Objekt in ref2 liefert wieder unsere Änderung zurück, die wir in ref1 vorgenommen haben.
    }
}

In diesem Code hast du zwar zwei Objektvariablen, aber nur ein Objekt. Egal ob du mit ref1 oder ref2 arbeitest, du arbeitest immer mit demselben Objekt. Und auf diese Referenzvariable bezieht sich final. Probiere mal das hier aus:

Java:
public class DontMessWithTheCompiler{
    final List theFinalList;
    
    public DontMessWithTheCompiler(){
        theFinalList = new ArrayList();
    }
    
    public void getThisCompiler(){
        theFinalList = new ArrayList();
    }
}
 

Neumi5694

Top Contributor
Ich denke, @Oneixee5 hat das Ganze richtig erkannt.
Final verhindert nur, dass die Variable eine neue Zuweisung erhält, nicht aber, dass sich der Inhalt ihres Objekts ändert. Dafür gibt's je nach Fall andere Hilfsmittel.
"Final Static" Klassenvariablen, die nicht in einem Einzeiler initialisiert werden können, können im static Block initialisiert werden. Der funktioniert sozusagen ähnlich wie ein Konstruktor, mit 2 Unterschieden.
1. hat er keine Parameter und 2. kann auch auf bereits zugewiesene Klassenvariablen nicht zugegriffen werden.
(und 3. gibt's klarerweise kein 'this')

Java:
class MyCLass {
    private static final Set<String> lockedThings;
  
    static {
        //das ginge alles auch in nur einer Zeile, das ist nur ein Beispiel
        var temp = new HashSet<String>();
        temp.add("harald");
        temp.add("echo");
        temp.add("kevin");
        lockedThings = Collections.unmodifiableSet(temp); //wenn wir schon dabei sind, dann sperren wir auch den Inhalt.
        //und nun zu dem, was NICHT geht.
        System.out.println(lockedThings.contains("bibo")); //auf lockedThings kann auf dieser Stelle nicht zugegriffen werden, das geht erst später über MyCLass.lockedThings
    }
}
 

no-cgpt

Mitglied
Danke für die gute Erklärung, @Neumi5694 . :)

Ich möchte noch hinzufügen, dass Strings immutable sind, das heißt, deren Inhalt kann nicht verändert werden. Gegebenenfalls muss man bei der unmodifiable Liste aber aufpassen, wenn man eigene Klassen als Datentyp verwendet, deren Inhalt geändert werden dürfte.

Es gibt ja drei Änderungsmöglichkeiten:

1. Die Variable an sich, (durch final sichergestellt)
2. Listenstruktur, (durch unmodifiable sichergestellt)
3. Listenelemente. (durch immutable sichergestellt)

Je nachdem, wie stark die Unveränderlichkeit sein soll, muss man sich dann um 1. bis 3. "kümmern".
 

Neumi5694

Top Contributor
Was ja ohnehin ein Anti-Pattern ist, das man nicht einsetzen sollte. Insofern stellt sich mir diese Frage gar nicht ... Natürlich kann man auch mit einem Hammer auf die Motorhaube schlagen, um diese zu öffnen, aber für gewöhnlich nimmt man den Knopf dafür.
... bis auf diejenigen, die deserialisieren. Manchmal ist selbst ein Hammer ein nützliches Werkzeug.

Es geht ja auch nicht um eine Anleitung, wie man's macht, sondern dass man sich als Programmierer bewusst sein sollte, dass es möglich ist und ein dritter das tun kann, obwohl man glaubt, den Inhalt geschützt zu haben.
 

White_Fox

Top Contributor
Ich wollte gerade sagen, wie will man denn ein Objekt z.B. in eine Datei schreiben oder zwischen Rechnern tauschen, ohne Reflexion?

Das ist auch so'n Ding weshalb ich den Begriff Antipattern nicht mag. Reflexion ist ein Werkzeug, wie jedes andere Sprachelement auch. Und Werkzeuge können für einen Zweck mehr oder weniger geeignet sein, aber nur weil jemand zu dusslig ist ein geeignetes Werkzeug zu wählen, macht es doch das Werkzeug nicht schlechter.

Und ja, eine Motorhaube mit einem Hammer öffnen zu wollen scheint erstmal dusslig, aber was willste machen wenn der Knopf z.B. klemmt, kauptt ist, nicht funktioniert? "Antipattern" hat irgendwie immer was von "Alle sind se blöde, außer ich". Zugegeben, oft genug ist das so, wenn ich da z.B. an die TableView aus JavaFX denke...gruslig. Aber trotzdem.
 

Neumi5694

Top Contributor
Ob man den Begriff nun mag oder nicht - er ist ja "richtig".
Leider wird er - was ich in diesem Fall gar nicht behaupten will - all zu oft missbraucht, hier im Forum des öfteren für persönliche Vorlieben, um sie wichtiger klingen zu lassen.

Das System hat durchaus seine Daseinsberechtigung, aber in einer "normalen" Anwendung sollte man nie davon Gebrauch machen müssen.
In dieser Auflistung - ohne offizielle Aussagekraft - fehlt es z.B., wird nur erwähnt, wenn man es 'falsch' anwendet.
Ich würde Reflection nicht verwenden, aber ich müsste mir schon einen absuchen, um dessen Verwendung irgendwo als Antipattern gelistet zu sehen.
 

KonradN

Super-Moderator
Mitarbeiter
Was mir nicht gefällt ist: man baut damit eine Art absolute Positon auf. Und das ohne Begründung.

Das ist aus meiner Sicht nicht ok. Ja, man kann (speziell nfängern) einfache Regeln an die Hand geben. Was haben sie wie zu machen? Aber immer mit einer Begründung und dann nie als absolute Position.

Es sollte aber immer so sein, dass sich Leute das Wieso / Weshalb klar machen und mit etwas mehr Überblick das dann eigenständig beurteilen können.

Was dann bleibt ist dann nur noch ein einfacher „Code smell“ - Sprich: es „riecht“ - es ist eine Auffälligkeit, wo man noch mal genauer drauf schauen möchte.
 

no-cgpt

Mitglied
Was dann bleibt ist dann nur noch ein einfacher „Code smell“ - Sprich: es „riecht“ - es ist eine Auffälligkeit, wo man noch mal genauer drauf schauen möchte
Das ist falsch, ein Smell ist nicht so schlimm wie ein Anti-Pattern.

Ich verstehe manchmal nicht, wieso Leute falsche Antworten geben müssen, wenn sie sich selber nicht sicher sind ... das hat bestimmt eine krankheitsbedingte Ursache ... zum Beispiel: eine Impulskontrollstörung.

Das wäre an für sich auch nicht schlimm, wenn dadurch nicht Dritte und das Forum im Ganzen in Mitleidenschaft gezogen würden.
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
M Apache Proxy Weiterleitung auf Tomcat funktioniert nicht wie gewünscht Allgemeine Java-Themen 1
W While Schleife funktioniert nicht ganz Allgemeine Java-Themen 4
H do-while Schleife funktioniert nicht wie ich es möchte Allgemeine Java-Themen 7
ERlK JDA Code funktioniert nicht? Allgemeine Java-Themen 4
B HeapSort für Array of Strings funktioniert nur teilweise Allgemeine Java-Themen 3
stormyark TikTakToe funktioniert nicht Allgemeine Java-Themen 10
T Remove bei ArrayList funktioniert nicht Allgemeine Java-Themen 2
M Map<String,String>funktioniert nicht richtig Allgemeine Java-Themen 4
P String.replace() funktioniert nicht? Allgemeine Java-Themen 3
boschl2000 Springerproblem-Implementierung funktioniert nicht richtig Allgemeine Java-Themen 1
F Getter Methode aufrufen funktioniert nicht Allgemeine Java-Themen 1
N Regulärer Ausdruck funktioniert nicht Allgemeine Java-Themen 6
Lukas2904 Wie funktioniert ein KeyLogger? Allgemeine Java-Themen 3
Tobero Meine Funktion für das beinhalten eines Punktes in einem Kreis funktioniert nicht Allgemeine Java-Themen 5
1Raini Java if-Abfrage funktioniert nicht! Allgemeine Java-Themen 3
Killunox MaxHeap Zuweisung unter Linux funktioniert nicht Allgemeine Java-Themen 1
I Wieso funktioniert das nich? Allgemeine Java-Themen 5
Dann07 MP3 Datei abspielen funktioniert nicht Allgemeine Java-Themen 6
O Aus JAR-Datei erstellte EXE-Datei funktioniert nicht Allgemeine Java-Themen 10
A Mp3 Player funktioniert nicht Allgemeine Java-Themen 0
X JNA funktioniert nicht mehr Allgemeine Java-Themen 4
bueseb84 FolderWatcher mit WatchService funktioniert nur bedingt Allgemeine Java-Themen 5
Drachenbauer Division mit Int funktioniert nicht Allgemeine Java-Themen 3
O docx-Datei erzeugung mit DocXStamper funktioniert nicht Allgemeine Java-Themen 2
F Schleife funktioniert nicht richtig Allgemeine Java-Themen 13
T Split() Methode funktioniert nicht?! Allgemeine Java-Themen 11
L Tesseract-OCR 4.0 unter Linux funktioniert nicht Allgemeine Java-Themen 3
J Wie konkret funktioniert das Modulsystem unter Java 11? Allgemeine Java-Themen 4
J Neuronales Netz funktioniert mal und mal nicht. Allgemeine Java-Themen 3
T Umlaute in Eclipse einlesen funktioniert nicht Allgemeine Java-Themen 16
A Methodenaufruf funktioniert nicht richtig Allgemeine Java-Themen 5
C WindowBuilder Design funktioniert nicht Allgemeine Java-Themen 0
J FTPSClient funktioniert nicht Allgemeine Java-Themen 4
H IDEA IntelliJ Java Mail funktioniert nach Export nicht mehr! Allgemeine Java-Themen 1
M Operatoren Warum funktioniert diese überprüfung nicht? Allgemeine Java-Themen 7
R jar-Datei funktioniert nicht Allgemeine Java-Themen 2
E Open Declaration Funktioniert nicht Allgemeine Java-Themen 0
R Verschlüsselung funktioniert nicht Allgemeine Java-Themen 5
RalleYTN requires transitive funktioniert nicht? Allgemeine Java-Themen 7
R Bruteforce hashes mit multithreading. Funktioniert das so? Allgemeine Java-Themen 0
P Best Practice Wieso funktioniert der Modulo - Operator nicht? Allgemeine Java-Themen 2
HarleyDavidson Eigener PropertyChangeListener funktioniert einfach nicht Allgemeine Java-Themen 3
J Exclude funktioniert nicht Allgemeine Java-Themen 2
K .jar funktioniert nicht vollständig Allgemeine Java-Themen 1
P Java https proxy (-Dhttps.proxyHost) Start-Parameter funktioniert nicht? Allgemeine Java-Themen 2
L Auswertung eines Testes funktioniert nicht Allgemeine Java-Themen 37
O Fahrenheit/Celsius Converter funktioniert nicht Allgemeine Java-Themen 2
M Serialisierung funktioniert nicht Allgemeine Java-Themen 9
D Collections.sort funktioniert nicht in exportierten .class Dateien Allgemeine Java-Themen 10
J Arrays auf gleichheit untersuchen funktioniert nicht Allgemeine Java-Themen 11
P GUI: ArrayList anzeigen funktioniert nicht Allgemeine Java-Themen 5
H Timer funktioniert nicht? Allgemeine Java-Themen 3
R javax.comm --> Programm funktioniert nach Export nicht mehr Allgemeine Java-Themen 0
O Mein JButton Array funktioniert nicht Allgemeine Java-Themen 3
R Erste Schritte Object reference funktioniert nicht. Wie mach ichs richtig? Allgemeine Java-Themen 3
J If Abfrage funktioniert nicht Allgemeine Java-Themen 4
R Objekt funktioniert nicht auf iOS Allgemeine Java-Themen 15
U PersistenceManager.createEntityManager funktioniert nicht Allgemeine Java-Themen 3
D Java Datei nach Eclipse Export funktioniert nicht Allgemeine Java-Themen 0
M Eigene forEach()-Methode funktioniert nicht. Allgemeine Java-Themen 2
H File.listFiles() funktioniert nicht... Allgemeine Java-Themen 10
JG12111989 Auswertung von Fragebogen funktioniert nicht! Allgemeine Java-Themen 7
M Primzahlberechnung funktioniert nicht. Allgemeine Java-Themen 4
A JFreeChart funktioniert nicht :( Allgemeine Java-Themen 6
C file.delete() funktioniert bei zweiten aufruf nicht mehr Allgemeine Java-Themen 3
F Datei einlesen funktioniert nicht Allgemeine Java-Themen 3
A Debugger im Java-Editor funktioniert nicht Allgemeine Java-Themen 5
B DB-Zugriff einer Webanwendung funktioniert nicht mit Java 7 Allgemeine Java-Themen 2
B Web-Anwendung funktioniert mit Java 1.8, aber nicht mit Java 1.7 (auf Client) Allgemeine Java-Themen 5
J Swing Cursor.WAIT funktioniert nicht nach JFileChooser Allgemeine Java-Themen 1
P Wie funktioniert das Feedback eines Klicks auf eine Java GUI Allgemeine Java-Themen 10
F JTextField funktioniert nicht Allgemeine Java-Themen 6
Athena Programm funktioniert nur beim Debugging korrekt, sonst nicht. Allgemeine Java-Themen 1
S CSV Eintrag der nächsten Zeile auslesen funktioniert nicht Allgemeine Java-Themen 8
S Command funktioniert in Kommandzeile aber nicht mit ProcessBuilder bzw. Runtime.exec auf MAC Allgemeine Java-Themen 3
G Verschlüsselungsalgorythmus funktioniert nicht Allgemeine Java-Themen 2
buggy84 Ausführen einer Batch mit Parameterübergabe funktioniert nicht richtig Allgemeine Java-Themen 18
G Befehl funktioniert in Eclipse allerdings nicht in einer Jar-Datei Allgemeine Java-Themen 3
N Werte aus Arrays auslesen funktioniert nicht Allgemeine Java-Themen 5
W getResources funktioniert nur in Eclipse, nicht in JAR Allgemeine Java-Themen 2
S Methode funktioniert nicht als ActionListener Allgemeine Java-Themen 4
M exec() funktioniert nicht Allgemeine Java-Themen 1
M RC4-Chiffre (funktioniert eingeschränkt) Allgemeine Java-Themen 6
X Datentypen Dropzone.options funktioniert nicht Allgemeine Java-Themen 1
D Java funktioniert nur mit deaktivierter Grafikkarte Allgemeine Java-Themen 3
L Erste Schritte Eclipse und Lokal funktioniert - in HTML nicht! Allgemeine Java-Themen 2
K MD5 funktioniert nicht korrekt !? Allgemeine Java-Themen 9
M JAR Datei erstellen funktioniert nicht Allgemeine Java-Themen 5
Q JLabel Textausgabe funktioniert nicht Allgemeine Java-Themen 4
E SimpleDateFormat-Konvertierung funktioniert nicht Allgemeine Java-Themen 3
T Dateidownload Funktioniert nicht Allgemeine Java-Themen 4
C Wie funktioniert Projektplanung? Allgemeine Java-Themen 18
K String.replace funktioniert nicht Allgemeine Java-Themen 3
G treeMap.putall funktioniert nicht?! Allgemeine Java-Themen 2
DaniSahne96 Threads Code funktioniert nicht wie er sollte Allgemeine Java-Themen 9
S Warum funktioniert die runable -.jar nicht? Allgemeine Java-Themen 7
P Eclipse Unter Windows erstelle .jar unter Linux (Ubuntu) funktioniert nicht Allgemeine Java-Themen 5
H Mit Ant erstelltes jar funktioniert nicht wie direkt in Eclipse Allgemeine Java-Themen 8
aze Jar ausführen über Runtime.execute funktioniert nicht Allgemeine Java-Themen 4
M Normalized Iteration count funktioniert nicht. Wo ist mien Denkfehler? Allgemeine Java-Themen 6

Ähnliche Java Themen

Neue Themen


Oben