2012-11-20 8 views
7

Okay, so weit ich weiß, verstehe ich diese Dinge über eine final Variable.Beschwerde gegen endgültige Variable

  1. Es sollte sollte vor dem Konstruktor initialisiert werden nur einmal
  2. Alle final Variablen zugewiesen werden vervollständigt

nun die oben mit, ich verstehe nicht, wie die unten nicht funktioniert:

Hier, bevor der Konstruktor abgeschlossen final Variablen werden gesetzt. Warum also klagen die Compiler dagegen?

+3

Was ist die Art von 'otherthing'? – maerics

+2

Hier ist das JLS-Kapitel über die definitive Zuweisung für Sie. http://docs.oracle.com/javase/specs/jls/se7/html/jls-16.html Viel Spaß. –

+1

Endgültige Variablen sind schön, aber es gibt viele Male, die sie einfach nicht sinnvoll sind. Wenn Sie keine Möglichkeit haben, es aus Ihrer Klasse heraus zu setzen, ist es immer noch "logisch", also werden Sie nicht zu lange damit aufhören, es zu erzwingen. Berücksichtigen Sie auch die Gültigkeit des Aufrufs einer Methode (die davon ausgeht, dass Ihre Klasse in einem fertigen Zustand ist) von einem Konstruktor (verantwortlich für das Beenden des Klassenstatus). Dies muss mit Sorgfalt geschehen. –

Antwort

18

Es ist nicht notwendig, dass Ihre Methode nur vom Konstruktor aufgerufen wird, sie kann auch von außerhalb des Konstruktors aufgerufen werden. Und sogar ein zweiter Aufruf könnte zu demselben Konstruktor in Zukunft hinzugefügt werden.

Obwohl Sie es jetzt vielleicht nicht verwendet haben, aber Compiler kann nicht sicher sein, so dass es nicht erlaubt ist. In Fachsprache gibt es keine definite assignment.

Für z: - Angenommen, Sie Ihre Klasse von main instanziiert: -

public static void main(String[] args) { 
    FinalTest obj = new FinalTest(something); 

    obj.setStuff(something); // There you go. This cannot be prevented. 
} 

Siehe JLS - Definite Assignments für detaillierte Erklärung zu diesem Thema.

+0

+1 gute Erklärung :) – PermGenError

+0

@GanGnaMSStYleOverFlowError .. Danke :) –

+4

Diese Erklärung macht keinen Sinn, denn wenn ich es privat mache, dann sollte es mir erlauben, es durch diese Erklärung zu tun. Der wahre Grund ist, dass es keine eindeutige Zuordnung gibt. –

8

Weil niemand Sie daran hindert, setStuff() ein zweites Mal später im Leben des Objekts zu nennen, was illegal wäre.

final Felder können nur in Codeblöcken zugewiesen werden, die garantiert nur einmal ausgeführt werden, dh Konstruktoren und Instanzinitialisierer. (Oder ein statischer Initialisierer im Falle eines static final Feldes.)

Mehr dazu finden Sie in der JLS.

+2

auch erwähnenswert, dass es möglich ist, eine letzte Variable in zwei verschiedenen Zuständen (Null und zugewiesenen Wert) zu beobachten, wenn der endgültige durch eine überschreibbare Methode im Konstruktor zugegriffen wird (weshalb Konstruktoren nie überschreibbare Methoden aufrufen sollten) – cfeduke

+0

@cfeduke One aus den vielen Gründen, ja. – biziclop

3

, da der Compiler nicht weiß, dass der einzige Anruf

public void setStuff(Something something) { 
    this.something = something; 
    this.otherthing = new SomeClass(something); 
} 

vom Konstruktor ist

0

Sollte die folgende Zeile

private final otherthing; 

so etwas wie

private final Something otherthing; 
sein

Sie vermissen die Klasse.

+0

adressiert nicht die Frage –

0

nur eine Randnotiz:

@Override 
public void setStuff(Something something) { 
    this.something = something; 
    this.otherthing = new SomeClass(something); 
} 

public FinalTest(Something something) { 
    setStuff(something); 
} 

Das ist wirklich ein schlechtes Design ist. Sie sollten eine überschreibbare Methode nicht vom Konstruktor aus aufrufen.

+0

Ich weiß, dass es nicht auf das konkrete Problem bezogen ist. Aber ich denke, es ist ein guter Ratschlag. Warum runterstimmen? –

+0

weil es nicht auf das konkrete Problem bezogen ist –

+0

Ich denke, es wurde downvoted, weil es nicht wirklich eine Antwort ist, sollte stattdessen ein Kommentar sein. Es ist eine sehr nützliche Sache zu wissen und kann nicht oft genug wiederholt werden. – biziclop

Verwandte Themen