2012-11-20 49 views
7

好的,據我所知,我瞭解這些有關final變量的內容。針對最終變量的投訴

  1. 應分配一次
  2. 所有final變量應該在構造函數之前被初始化完成

現在使用上面,我不明白是怎麼以下不工作:

public class FinalTest implements AnotherClass { 

    private final Something something; 
    private final otherthing; 

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

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

這裏,在構造函數完成之前final變量正在設置。那爲什麼編譯器會抱怨呢?

+3

「otherthing」的類型是什麼? – maerics

+2

以下是關於明確分配給您的JLS章節。 http://docs.oracle.com/javase/specs/jls/se7/html/jls-16.html享受。 –

+1

最終變量很好,但有很多次他們沒有意義。如果你沒有辦法在課堂上設置它,那麼它仍然是「邏輯上」的最終選擇,所以不要太強迫它。還要考慮從構造函數(負責完成類的狀態)調用方法(假定您的類處於完成狀態)的有效性。這需要謹慎處理。 –

回答

18

您的方法不需要僅從構造函數中調用,它也可以從構造函數外部調用。甚至第二次調用也可能會在未來添加到相同的構造函數中。

即使您現在可能還沒有使用它,但編譯器無法確定它,因此它不允許使用它。在技​​術術語中,沒有definite assignment

對於e.g: -假設你從main實例類: -

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

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

JLS - Definite Assignments查找有關此詳細解釋。

+0

+1好解釋:) – PermGenError

+0

@GanGnaMStYleOverFlowErroR ..謝謝:) –

+4

這個解釋沒有意義,因爲如果我把它變成私人的,那麼它應該允許我通過這個解釋來做到這一點。真正的原因是沒有明確的任務。 –

8

因爲沒有人阻止你在對象的生命中第二次調用setStuff(),這將是非法的。

final字段只能在保證只運行一次的代碼塊中分配,即構造函數和實例初始化程序。 (或在static final字段的情況下爲靜態初始化程序)。

關於此問題的更多信息,請參見JLS

+2

另外值得一提的是,如果最終被構造函數中的可重寫方法訪問(這就是爲什麼構造函數不應該調用可覆蓋的方法),可以觀察到兩個不同狀態(空值和賦值)的最終變量 – cfeduke

+0

@cfeduke One有很多原因,是的。 – biziclop

3

,因爲編譯器不知道的唯一呼叫

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

是從構造

0

如果下面一行是

private final otherthing; 

private final Something otherthing; 

你錯過了班級。

+0

沒有解決問題 –

0

只是一個側面說明:

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

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

這真是一個糟糕的設計。您不應該從構造函數調用可重寫的方法。

+0

我知道這不是真正的具體問題。但我認爲這是一個很好的建議。爲什麼downvote? –

+0

,因爲它與具體問題無關 –

+0

我認爲它被低估了,因爲它不是一個真正的答案,應該是一個評論。這是一件非常有用的事情,但不能重複足夠的時間。 – biziclop