Du verwendest einen veralteten Browser. Es ist möglich, dass diese oder andere Websites nicht korrekt angezeigt werden. Du solltest ein Upgrade durchführen oder ein alternativer Browser verwenden.
ich komme gleich zur Frage: Wenn mittels einer Setter-Methode eine Variable, welche mit final deklariert wurde, verändert werden soll, wie gehe ich dann hierbei vor?
Beispielcode:
public void setZAchse(final double z){
setZAchse(z);
}
wäre dies korrekt? Mir wird kein Fehler im Programm angezeigt. Jedoch habe ich gelesen, dass dieser Vorgang für final-Attribute nicht zulässig sei.
Ich hoffe, die Frage ist verständlich formuliert. Bin noch Anfängerin
Dein Code erstellt eine Mwthode, die sich selbst aufruft? Damit bekommst du nur eine StackOverflowException.
Einer final Variablen kann man keinen neuen Wert zuweisen (nur einmal bei der Initialisierung direkt bei der Deklaration oder im Konstruktor).
In dem Beispiel von dir sehe ich nur ein final- bei dem Parameter. Das ist ein Best practice, weil dadurch nicht versehentlich dem Parameter ein neuer Wert zugewiesen wird. Das hat aber auf irgendwelche Instanzvariablen keinen Einfluss.
Dein Code erstellt eine Mwthode, die sich selbst aufruft? Damit bekommst du nur eine StackOverflowException.
Einer final Variablen kann man keinen neuen Wert zuweisen (nur einmal bei der Initialisierung direkt bei der Deklaration oder im Konstruktor).
In dem Beispiel von dir sehe ich nur ein final- bei dem Parameter. Das ist ein Best practice, weil dadurch nicht versehentlich dem Parameter ein neuer Wert zugewiesen wird. Das hat aber auf irgendwelche Instanzvariablen keinen Einfluss.
Könntest du mir sagen, wie ich das verständlicher hätte formulieren können?
Danke für den Hinweis, das habe ich nicht gewusst, dass damit ein StackOverflowException ausgeworfen wird.
Was ist wenn die Variable erst in der Setter-Methode zu final wird? Geht sowas? Also dass die Variable "double z" davor ohne final deklariert wurde und im Nachhinein in der Setter-Methode zu final wird.
Hoffe, dies lässt sich diesmal etwas besser verstehen
public void doSomething(final int someParameter) {
// ..
someParameter = 42; // geht nicht!
}
Die Variable/Parameter "someParameter" ist eine lokale Variable der Methode "doSomething" mit dem final sagst du nur, dass der Wert innerhalb der Methode nicht mehr neu zugewiesen werden kann. Die einzige mögliche Zuweisung erfolgt im Aufruf der Methode.
Bei einer finalen Instanzvariablen kannst du sie entweder sofort initialisieren oder im Konstruktor:
Java:
class Foo {
private final int value = 42;
}
// oder
class Foo {
private final int value;
Foo(final int value) { // das final hier, siehe oben
this.value = value;
}
}
Final ist allerdings nicht unbedingt ganz final. Falls es sich bei dem in der Variablen gespeicherten Wert um eine Referenz handelt, dann kannst du zwar diese Referenz nicht ändern, aber den Inhalt dessen, worauf referenziert wird, möglicherweise doch:
Java:
class Ref {
public int value;
}
void someMethode(final Ref someParameter) {
someParameter = new Ref(); // geht nicht!
someParameter.value = 42; // geht
}
Du könntest allerdings die Instanzvariable "value" in der Klasse "Ref" final machen, dann geht es wieder nicht mehr.
Danke für den Hinweis, das habe ich nicht gewusst, dass damit ein StackOverflowException ausgeworfen wird.
Was ist wenn die Variable erst in der Setter-Methode zu final wird? Geht sowas? Also dass die Variable "double z" davor ohne final deklariert wurde und im Nachhinein in der Setter-Methode zu final wird.
Hoffe, dies lässt sich diesmal etwas besser verstehen
Vielleicht erstmal ein paar Worte zu Methodenaufrufen. Wenn Du eine Methode aufrufst, wird im Stackbereich der JVM ein Stack-Frame unter anderem für die Parameter eingerichet, die in Java grundsätzlich als Kopie (Call by Value) an die aufgerufene Methode übergeben werden. Der Stack-Frame braucht Platz und der ist begrenzt. Wenn Du also eine Methode hast, die sich immer selbst aufrufst, dann ist der Platz irgendwann zu Ende, der Stack ist überfüllt und daher bekommst Du die StackOverflowException.
Wichtig für das weitere Verständnis ist das bereits angesprochene Call by Value. Der Parameter in Deiner Methode erhält bei jedem Aufruf eine Kopie des übergebenen Werts. Wenn Du den Parameter final machst, kannst Du dem Parameter innerhalb der Methode keinen anderen Wert zuweisen. Du kannst den Parameter aber in beliebigen anderen Methoden verwenden, weil er ja beim Methodenaufruf wieder nur kopiert wird.
Am Anfang ist es natürlich schwer, immer alles richtig zu formulieren. Das war auch nicht als Vorwurf gedacht, sondern es ist lediglich ein HInweis, denn im Anschluss konnte ich nur versuchen, auf das einzugehen, das ich verstanden habe.
Diese Wortwahl ist nicht ganz korrekt. Die Java Language Specification unterscheidet zwischen Parametern und lokalen Variablen. Eine lokale Variable. Abschnitt 4.12.3 hat Parameter in der Auflistung als Punkt 4 und lokale Variablen in Punkt 8.
Das ist auch extrem missverständlich. Die Variable ist und bleibt final. Aber was Du dann erläuterst stimmt natürlich wieder. Aber so gewisse Aussagen finde ich eher verwirrend.
Evtl. einmal von meiner Seite ein paar Worte zu final:
final ist ein Attribut, das besagt, dass eine Variable nach der Initialisierung nicht mehr verändert werden kann. Evtl. einfach einmal die bildliche Vorstellung dazu:
Variablen sind Zettel. Die Zettel haben einen bestimmten Vordruck, und daher können nur bestimmte Dinge auf einen Zettel geschrieben werden. (Das wäre der Typ). Auf einen Zettel für eine ganze Zahl (int) kann daher nur eine solche Zahl geschrieben werden.
final bedeutet nun, dass der Zettel nach dem ersten Beschreiben in Folie eingeschlossen wird. Dadurch kann der Wert nicht mehr verändert werden. Wenn auf dem Zettel eine Adresse steht (Referenz), dann kannst Du natürlich mit dem Objekt an der Adresse Dinge machen.
Nur weil der Zettel mit der Adresse so gemacht wurde, dass die Adresse nicht geändert werden kann, kannst Du das Haus beschädigen, Dinge entwenden, u.s.w. (Also das, was temi etwas meinte)
Um es ganz konkret zu machen: final Variablen werden in der Java Language Specification in 4.12.4 beschrieben:
A variable can be declared final. A final variable may only be assigned to once. It is a compile-time error if a final variable is assigned to unless it is definitely unassigned immediately prior to the assignment (§16 (Definite Assignment)).
Once a final variable has been assigned, it always contains the same value. If a final variable holds a reference to an object, then the state of the object may be changed by operations on the object, but the variable will always refer to the same object. This applies also to arrays, because arrays are objects; if a final variable holds a reference to an array, then the components of the array may be changed by operations on the array, but the variable will always refer to the same array.
Das ist die Bedeutung, aber wichtig ist noch: final ist ein Modifier der Variable. Also eine Variable ist es oder ist es nicht. Du kannst es nicht im Nachhinein anpassen (Reflection und so vergessen wir an dieser Stelle einmal - JLS 17.5.3 geht da aber auch etwas drauf ein)
Du hast jetzt ein Parameter final gemacht - dazu habe ich schon geschrieben, dass dies ein gutes "Best Practice" ist.
Um das zu erkennen, nehmen wir uns einfach ein kleines Beispiel und machen dann ein "Refactoring" - wir bennen etwas um:
Java:
public class Test {
private int value;
public void setValue(int v) {
value = v;
}
}
Wir haben eine Klasse mit einem Feld value und dazu ein Setter. Der Setter bekommt ein Parameter v. Das ist natürlich blöd - so "Abkürzungen" wollen wir nicht, also benennen wir es um zu value:
Java:
public class Test {
private int value;
public void setValue(int value) {
value = value;
}
}
Das ist jetzt aber doof - der Parameter value versteckt die Instanzvariable value. Da hätten wir schreiben müssen: this.value = value;
Ein einfaches Beispiel für ein mögliches Problem....
Aber auch vom Verständnis her: Es ist ja schon erwähnt worden: Wir haben Call By Value - es wird also immer nur eine Kopie übergeben. Wenn ich also einer Methode als Parameter eine Variable mitgebe, dann wird diese Variable nie geändert. Eine Zuweisung ist somit in der Regel nicht sinnvoll.
Und als Letztes aus meiner Sicht das wichtigste Argument:
Code sollte sauber strukturiert sein. Es gibt also eine klare Eingabe in die Methode, dann eine Verarbeitung und dann eine Rückgabe. Das sollte man sauber trennen und nicht mischen. Wenn eine Methode einen Parameter hat, dann ist das die Eingabe und die würde ich nicht anderweitig verwenden.
Das einfach einmal von meiner Seite noch zu diesem Thread.