Variablen final String Variable als Attribut veränderbar?

R

rattosch

Gast
Hallo,

angenommen ich habe als Attribut

Java:
private final String name;

dann bedeutet das doch, dass ich den Variablenwert nicht ändern kann. Da es sich hier um eine Referenzvariable handelt, dürfte also der Referenzwert nicht verändert werden können. Dieser ist doch defaultmässig null. Das würde doch bedeuten das ich die null Referenz nicht mehr ändern kann, oder?

Warum funktioniert es aber wenn ich einen Konstruktor schreibe ala

Java:
public Test(String name) { this.name = name; }

In diesem Fall ändere ich doch den Wert bzw. die Referenz der als final deklarierten Variable. Was ja eigentlich nicht gehen dürfte, da das Attribut ja schon mit null belegt ist. Bin momentan etwas verwirrt. Evtl. kann mir jemand die Frage beantworten.
 
B

Beni

Gast
Du kannst den Wert genau einmal setzen (einmal initialisieren), und der Compiler wird eine Fehlermeldung ausgeben wenn du auch nur ansatzweise versuchst die Variable zweimal zu ändern (probier es aus, schreib "this.name = ..." an mehr als einer Stelle hin).
 

musiKk

Top Contributor
Du kannst den Wert genau einmal setzen (einmal initialisieren)

Man muss diesen Wert sogar genau einmal setzen. Allerdings geht das auch nur in bestimmten Situationen. Bei Klassenvariablen ist dies entweder der Konstruktor oder Initializer. Es muss zur Compilezeit bewiesen werden können, dass die Variable durch jeden möglichen Pfad (if-else-Zweige, switch, etc.) genau einmal gesetzt wird.
 
B

bygones

Gast
und zur ergaenzung.
Java:
public final List<String> list = new ArrayList();

// some code
list.add("foo");
list.remove("foo");
d.h. der Inhalt einer finalen Variable laesst sich immer aendern (wenn dieser nicht selbst immutable ist).
 
R

rattosch

Gast
Hallo,

genau einmal setzen. Das müsste mit null ja passieren und trotzdem kann ich, nachdem der Wert genau einmal auf null gesetzt wurde noch eine Referenz setzen.
 

tfa

Top Contributor
Das müsste mit null ja passieren und trotzdem kann ich, nachdem der Wert genau einmal auf null gesetzt wurde noch eine Referenz setzen.
Wo setzt du den Wert auf null? In deinem Codeausschnitt steht davon nichts.

d.h. der Inhalt einer finalen Variable laesst sich immer aendern (wenn dieser nicht selbst immutable ist).
Nicht der Inhalt. Der Zustand des Objekts, das in einer finalen Variable gespeichert ist, lässt sich ändern.
 

musiKk

Top Contributor
Wo setzt du den Wert auf null? In deinem Codeausschnitt steht davon nichts.

Naja, Klassenvariablen sind per Default null/0/0.0/false, das stimmt schon. Das mit final ist eben ein Sonderfall. Initialisierung und Zuweisung sind in der JVM zwei Verschiedene Dinge. final erzwingt eine Zuweisung, die über die Initialisierung hinausgeht.

Nicht der Inhalt. Der Zustand des Objekts, das in einer finalen Variable gespeichert ist, lässt sich ändern.

Ich denke, das war gemeint. Über exakte Bezeichnungen können wir sicher stundenlang diskutieren ohne Inhalt beizusteuern.
 
B

bone2

Gast
Naja, Klassenvariablen sind per Default null/0/0.0/false, das stimmt schon.

[EDIT]ach du meinst nicht final variablen, okay. falsch verstanden[/EDIT]

also mein compiler streikt wen ich die nicht initialisiere

Code:
e:\w2\testarea\src>javac Test2.java
Test2.java:19: error: variable i might not have been initialized
        System.out.println(i);
                           ^
Test2.java:20: error: variable b might not have been initialized
        System.out.println(b);
                           ^
Test2.java:21: error: variable s might not have been initialized
        System.out.println(s);
                           ^
Test2.java:22: error: variable o might not have been initialized
        System.out.println(o);
                           ^
4 errors
Java:
public class Test2 {
    private final Object o;
    private final int i;
    private final boolean b;
    private final String s;

    public Test2() {
        System.out.println(i);
        System.out.println(b);
        System.out.println(s);
        System.out.println(o);
    }

    public static void main(String[] args) throws IOException {
        Test2 test = new Test2();

    }

oder mache ich was falsch?
 
R

rattosch

Gast
Hallo,

also verstehe ich es jetzt so richtig:

Das Attribut

private final String name; wird default mit null initialisiert. Jetzt muss ich aber eine Zuweisung einmalig vornehmen, da final eine Zuweisung erzwingt. Nach dieser Zuweisung (Referenz) kann ich keine neue Referenz zuweisen.
 

Ark

Top Contributor
Das Attribut

private final String name; wird default mit null initialisiert.
Nein, und warum, hast du eigentlich schon selbst geschrieben (und tfa):
Jetzt muss ich aber eine Zuweisung einmalig vornehmen, da final eine Zuweisung erzwingt.
Genau!
Nach dieser Zuweisung (Referenz) kann ich keine neue Referenz zuweisen.
So kann man das sagen, ja.

Auf allen möglichen Wegen durch die Anweisungen jedes Konstruktors gibt es eine und nur eine Zuweisung für (in diesem Fall) name.

Spricht eigentlich was dagegen, dies einfach mit einem Compiler auszuprobieren? Er wird schon meckern, wenn ihm was nicht passt.

Ark
 

xehpuk

Top Contributor
Meines Erachtens stimmt die Aussage, dass die Variable immer mit einem Defaultwert initialisiert wird:
Each class variable, instance variable, or array component is initialized with a default value when it is created (§15.9, §15.10):
4.12.5. Initial Values of Variables

Java:
public class VariableTest {
	private final String name;

	public VariableTest() {
		System.out.println(this.name);
		name = "name";
	}
	
	public static void main(final String... args) {
		new VariableTest();
	}
}
Das liefert mir
Code:
null
.

Interessanterweise kriege ich einen Compilerfehler, wenn ich das
Code:
this
weglasse:
Java:
public class VariableTest {
	private final String name;

	public VariableTest() {
		System.out.println(name); // variable name might not have been initialized
		name = "name";
	}
	
	public static void main(final String... args) {
		new VariableTest();
	}
}

Gleiches Problem mit Klassenvariablen:
Java:
public class VariableTest {
	private static final String name;

	static {
		System.out.println(VariableTest.name);
		name = "name";
	}
	
	public static void main(final String... args) {}
}
Liefert
Code:
null
.

Compilerfehler ohne
Code:
VariableTest
:
Java:
public class VariableTest {
	private static final String name;

	static {
		System.out.println(name); // variable name might not have been initialized
		name = "name";
	}
	
	public static void main(final String... args) {}
}

Kann mir das jemand erklären?
 

MrClave

Bekanntes Mitglied
Du gibst dir die Variable aus, bevor du sie initialisierst.
Kann ja dann nur null sein, weil's zum Zeitpunkt des ausgebens keinen Wert hat.

Tausch' sie um, und du wirst "name" erhalten.
 
Zuletzt bearbeitet:

xehpuk

Top Contributor
Du hast meinen Beitrag missverstanden.
Es ging mir darum, zu zeigen, dass Instanz- und Klassenvariablen bei ihrer Erstellung mit einem Defaultwert (in diesem Fall
Code:
null
) initialisiert werden.
Die Zuweisung an name habe ich nur gemacht, um einen Compilerfehler zu verhindern.
Während ich an dem Code arbeitete, fiel mir auf, dass es einen Compilerfehler gibt ("variable name might not have been initialized"), wenn man nicht voll qualifiziert (
Code:
this.name
bei der Instanz- und
Code:
VariableTest.name
bei der Klassenvariable) auf die Variable zugreift. Eine Erklärung habe ich dafür bisher nicht gefunden.
 
M

maki

Gast
Kann mir das jemand erklären?
Tippe auf einen Compilerbug.

IMHO sollte beides, also mit egal ob mit oder ohne this/Klassenname Qualifizierung, einen Compilerfehler erzeugen.

Der "Trick" an final ist u.a., dass bestimmte Annahmen gemacht werden können, zB. dass solche Variablen nicht uninitialisiert sein können (offensichtlich schon??) und dass alle Threads dasselbe zusehen bekommen.
 

Illuvatar

Top Contributor
Tippe auf einen Compilerbug.

IMHO sollte beides, also mit egal ob mit oder ohne this/Klassenname Qualifizierung, einen Compilerfehler erzeugen.

Hmm... der Compiler kann aber natürlich nicht immer in allen Fällen überprüfen, ob gerade das aktuelle Objekt angesprochen wird.
Wenn der Compiler hier meckern würde:
Java:
public class VariableTest {
    private final String name;
 
    public VariableTest() {
        System.out.println(this.name);
        name = "name";
    }
    
    public static void main(final String... args) {
        new VariableTest();
    }
}
Sollte er dann nicht eigentlich auch hier meckern?
Java:
public class VariableTest {
    private final String name;
 
    public VariableTest() {
        VariableTest foo = this;
        System.out.println(foo.name);
        name = "name";
    }
    
    public static void main(final String... args) {
        new VariableTest();
    }
}
Und was ist dann damit?
Java:
public class VariableTest {
    private final String name;
 
    public VariableTest() {
        VariableTest foo = lengthyComputationWhichAlwaysReturnsTrue() ? this : null;
        System.out.println(foo.name);
        name = "name";
    }
    
    public static void main(final String... args) {
        new VariableTest();
    }
}
 

KSG9|sebastian

Top Contributor
Nebenbei werden die Variablem bei erzeugen des Objekts mit Defaults initialisiert. Und das passiert beim Konstruktoraufruf (einfach mal debuggen, da sieht man es)
Final-Variablen werden auch nicht per Default mit null initialisiert sondern einmalig auf den Wert gesetzt bei der Zuweisung.
 

xehpuk

Top Contributor
Die Variablen werden schon vor dem Aufruf des Konstruktors/Instanzinitialisierers mit Defaultwerten initialisiert. Unabhängig davon, ob sie
Code:
final
sind oder nicht. Das haben die Ausgabe des Testcodes und auch der Debugger bei mir gezeigt.

Dazu dann auch ein Zitat aus der JVMS:
Memory for a new instance of that class is allocated from the garbage-collected heap, and the instance variables of the new object are initialized to their default initial values (§2.3, §2.4).
[…]
The new instruction does not completely create a new instance; instance creation is not completed until an instance initialization method (§2.9) has been invoked on the uninitialized instance.
Chapter 6.5 The Java Virtual Machine Instruction Set, Instructions, new

Ein
Code:
new Foo(bar)
in Java wird dann quasi zu
Code:
new Foo
und
Code:
invokespecial <init>(bar)
im Bytecode. Zwischen diesen Aufrufen beinhalten die Variablen dann die Defaultwerte.
 

musiKk

Top Contributor
Hmm... der Compiler kann aber natürlich nicht immer in allen Fällen überprüfen, ob gerade das aktuelle Objekt angesprochen wird.
Wenn der Compiler hier meckern würde:
...snip...
Sollte er dann nicht eigentlich auch hier meckern?
...snip...
Und was ist dann damit?
...snip...

In den ersten beiden Fällen sollte der Compiler eigentlich alle Informationen haben (beim Dritten scheiterts am Halteproblem). Über eine Datenflussanalyse sollte das eigentlich trivial sein. Allerdings zeigen sowohl javac als auch der JDT Compiler das gleiche Verhalten, was darauf schließen lässt, dass es wahrscheinlich aus der Spec hervorgeht. Ich habe jetzt allerdings eine ganze Weile danach gesucht (mir klingelt gerade der Kopf vor lauter "definite assignment" etc.) aber ich habe nichts gefunden. Hast Du ne Idee, woraus das hervorgehen könnte?
 

xehpuk

Top Contributor
Man kann den Compilerfehler ebenfalls über eine Methode umgehen:
Java:
public class VariableTest {
    private final String name;

    private VariableTest() {
        name();
        name = "name";
        name();
    }

	private void name() {
		System.out.println(name); // liefert trotz final nicht die gleiche Ausgabe
	}

    public static void main(final String... args) {
        new VariableTest();
    }
}
Code:
null
name
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
A final String verrechnen Java Basics - Anfänger-Themen 2
S final String Java Basics - Anfänger-Themen 2
T private final String oder final String? Was ist richtig? Java Basics - Anfänger-Themen 4
G public static void main(final String[] args) Java Basics - Anfänger-Themen 4
C Setter-Methode mit final-Attribut Java Basics - Anfänger-Themen 9
I Variable innerhalb Methode: Local variable test defined in an enclosing scope must be final or effectively final Java Basics - Anfänger-Themen 3
J final attribute erben Java Basics - Anfänger-Themen 2
L Methode implementieren, Parameter die übergeben werden sind final Java Basics - Anfänger-Themen 4
N Wie kann ich eine meine Variable Final machen? Java Basics - Anfänger-Themen 1
A Variablen zum final verändern Java Basics - Anfänger-Themen 4
D Interface Final für Parameter in überschriebenen Methoden? Java Basics - Anfänger-Themen 3
E Sinn: final in Parameterliste verwenden Java Basics - Anfänger-Themen 2
M Iterator cannot refer to a non final... Java Basics - Anfänger-Themen 20
shiroX Klassen Klasse/Methode private final jUnit-Fehler Java Basics - Anfänger-Themen 5
D Kapselung final Variablen mit Getter? Java Basics - Anfänger-Themen 2
R JTextArea final Status ändern Java Basics - Anfänger-Themen 11
F Static final Klasse Java Basics - Anfänger-Themen 0
S Kopierkonstrukter eines Objekts mit final Attributen Java Basics - Anfänger-Themen 6
T Schlüsselworte final Java Basics - Anfänger-Themen 1
M Wann final verwenden? Java Basics - Anfänger-Themen 5
F Methoden Cannot refer to a non-final variable.. verständnisproblem. Java Basics - Anfänger-Themen 7
C Klassen Minesweeper Problem. int needs to be final (inner class problem) Java Basics - Anfänger-Themen 3
U final Instanz Java Basics - Anfänger-Themen 11
W run Methode in Time erzwingt final Java Basics - Anfänger-Themen 3
D Polymorphie final class Java Basics - Anfänger-Themen 2
C Erste Schritte felder, die public final sind Java Basics - Anfänger-Themen 6
H static final vs. final static Java Basics - Anfänger-Themen 3
A final und extends Java Basics - Anfänger-Themen 14
N Bessere Performance durch final: wann denn überhaupt? Java Basics - Anfänger-Themen 28
xehpuk Compiler-Fehler final Variable in try-catch Wert zuweisen Java Basics - Anfänger-Themen 8
J final variablen Java Basics - Anfänger-Themen 3
P Variablen static final boolean Java Basics - Anfänger-Themen 9
S Interface Final und interface Java Basics - Anfänger-Themen 6
ruutaiokwu final wenn immer möglich verwenden? Java Basics - Anfänger-Themen 30
N local variable model is accessed from within inner class; needs to be declared final Java Basics - Anfänger-Themen 4
C Error: The final local variable variable cannot be assigned, since it is defined in an enclosing typ Java Basics - Anfänger-Themen 4
T Verständnis von "final" und "static" Java Basics - Anfänger-Themen 6
T In methode Final Objekte übergeben? Java Basics - Anfänger-Themen 9
C final variable Java Basics - Anfänger-Themen 4
G Poi 3.5-Final zum laufen bringen Java Basics - Anfänger-Themen 2
H final/static Vererbung Java Basics - Anfänger-Themen 4
P Can not refer to a non final variable... Java Basics - Anfänger-Themen 3
H Variablen final? Java Basics - Anfänger-Themen 3
T Warum muss diese Variable final deklariert werden? Java Basics - Anfänger-Themen 5
G final Variablen in enhanched-for Java Basics - Anfänger-Themen 2
V Frage zu final und Class bzw. Class.cast Java Basics - Anfänger-Themen 5
G static final Java Basics - Anfänger-Themen 7
Q Vector verändert trotz final seine Größe Java Basics - Anfänger-Themen 5
A final Variablen und der GarbageCollector Java Basics - Anfänger-Themen 2
G OOP - final Java Basics - Anfänger-Themen 2
B objekt wann als final deklarieren? Java Basics - Anfänger-Themen 2
G Sollte man Klassenvariablen als final deklarieren? Java Basics - Anfänger-Themen 3
J Interface: The final field Variablen.N cannot be assigned Java Basics - Anfänger-Themen 2
B privat mit und ohne final Java Basics - Anfänger-Themen 4
B final vor Funktionsparameter? Java Basics - Anfänger-Themen 21
D Static, final Objekte mit Exceptions im Konstruktor Java Basics - Anfänger-Themen 2
W Fehlermeldung "...needs to be declared final" ! Java Basics - Anfänger-Themen 4
N Wieso final ? Java Basics - Anfänger-Themen 4
G <identifier> expected bei public void final Java Basics - Anfänger-Themen 3
A Problem mit innerer Klasse/final Java Basics - Anfänger-Themen 2
G Methoden + variablen als final definieren? Java Basics - Anfänger-Themen 3
F enum oder static final boolean? Java Basics - Anfänger-Themen 18
M enum final Methoden Java Basics - Anfänger-Themen 24
N The serializable class.does not declare a static final . Java Basics - Anfänger-Themen 2
F public final void getsignature() | anfänger Java Basics - Anfänger-Themen 7
A class does not declare a static final serialVersionUID Java Basics - Anfänger-Themen 13
G wieso muss Textfield final sein? Java Basics - Anfänger-Themen 6
M Cannot refer to a non-final variable Java Basics - Anfänger-Themen 10
A array nach initialisierung final machen? Java Basics - Anfänger-Themen 17
G Warum muss das Textfeld final sein? Java Basics - Anfänger-Themen 2
P final mit Parametern Java Basics - Anfänger-Themen 3
krgewb String mit Datumsangabe in Long umwandeln Java Basics - Anfänger-Themen 2
D String Groß/Kleinschreibung Ignorieren Java Basics - Anfänger-Themen 4
D Map<String, Integer> sortieren und der reinfolge nach die Glieder abfragen Java Basics - Anfänger-Themen 3
J Ähnlichen String in Liste finden Java Basics - Anfänger-Themen 6
Kartoffel_1 String transformation Java Basics - Anfänger-Themen 7
H String-Operation replace() - Zeichenkette verdoppeln Java Basics - Anfänger-Themen 2
K String analysieren Java Basics - Anfänger-Themen 27
Beowend String zu Date parsen Java Basics - Anfänger-Themen 1
Beowend String auf Satzzeichen überprüfen? Java Basics - Anfänger-Themen 6
H Liste nach String-Länge sortieren Java Basics - Anfänger-Themen 1
String in ArrayList umwandeln Java Basics - Anfänger-Themen 1
I Sass Compiler und String erhalten? Java Basics - Anfänger-Themen 7
Avalon String in Double bzw. Währung konvertieren Java Basics - Anfänger-Themen 6
T Methode akzeptiert String nicht Java Basics - Anfänger-Themen 18
F Arraylist<String>Ein Wort pro Zeile Java Basics - Anfänger-Themen 6
J Schlüsselworte Prüfen, ob ein bestimmtes, ganzes Wort in einem String enthalten ist. Java Basics - Anfänger-Themen 6
N String überprüfen Java Basics - Anfänger-Themen 3
E String zerlegen aus args Java Basics - Anfänger-Themen 1
M Long-Typ in String-Änderung führt zu keinem Ergebnis bei großer Zahl Java Basics - Anfänger-Themen 11
Ostkreuz String Exception Java Basics - Anfänger-Themen 8
W Items löschen aus String Array vom Custom Base Adapter Java Basics - Anfänger-Themen 2
MoxMorris Wie macht man String[] = String[] aus einer anderer Methode? Java Basics - Anfänger-Themen 18
J String Filter Java Basics - Anfänger-Themen 5
S String Array Buchstaben um einen gewissen Wert verschieben Java Basics - Anfänger-Themen 4
R Größter zusammenhängender Block gleicher Zeichen im String Java Basics - Anfänger-Themen 1
XWing Randomizer mit einem String Java Basics - Anfänger-Themen 2
D 2D Char Array into String Java Basics - Anfänger-Themen 2
H Cast von Float nach String klappt nicht Java Basics - Anfänger-Themen 12
I Zerlegen von String Java Basics - Anfänger-Themen 3

Ähnliche Java Themen

Neue Themen


Oben