2011-12-20 20 views
1

這個下面的類是不可變的嗎?由於沒有構件是子類可見,因爲沒有setter方法它是不可變的類嗎?

  • 實例變量x不在最終

    class Immutable { 
    
        private int x; 
    
        Immutable(int value) { 
        this.x = value; 
        } 
    
        public int getX(){ 
        return x; 
        } 
    } 
    
    1. 類不是終點。

    有沒有可能這個類會打破Immutable功能的契約而不在這個類中添加任何代碼?

  • 回答

    3

    Joshua Bloch在他的「Effective Java」中指出「你應該爲你的類設計可擴展性或者使它們不可擴展」

    如果靈活性是您的首要關注點,並且您有充分的理由爲繼承設計您的不可變類 - 請將此類保留爲非最終類。

    如果安全是您關心的問題,請將此課程定爲最終成員並最終確定成員字段。因爲:

    • 通過重寫getter方法,可以擴展非最終類以創建可變子類。

    • Java是reflective的設計。正如Belgther所說,可以使用反射來設置成員字段的值。(不管是私人的還是公共的)很久以前,I used this將我的特定調試器與另一個項目集成在一起。

    +0

    非常感謝。公告中的這個答案已經徹底清除了我的問題。 –

    6

    該類幾乎是不可變的。

    但是你仍然可以使用反射來設置變量x的值,因爲變量不是最終的。

    +2

    我認爲即使'最終'變量是不安全的反射。沒有消息,抱歉。 – st0le

    +0

    oooh謝謝beigther。這個問題在我的採訪中被問到,我說完全沒問題。 –

    +0

    @ st0le IIRC,這是在版本之間改變的東西。有一種技術可以通過在Field對象上使用反射來去除明顯的'final'修飾符來設置最終變量。 –

    0

    是的,在我看來,它是不可變的。

    既然你有一個只能在構造函數中設置的私有字段,並且該類中的唯一方法是getter,那麼該字段不能再被修改,並且該類可以說是不可變的。

    6

    Immutable類是不可變的。

    但是,可以聲明其實例可變的Immutable的子類。事實上,防止這種情況的唯一方法是使這個類final ...或使其構造函數保密。

    您可能會爭辯(我會)Immutable的可變子類違反了Immutable的合同。


    使用反射改變值x的方法違反了規則。 Java規範說,這樣做的應用程序的行爲是未指定的。 (當然,它打破了JLS表示JIT編譯器允許製作的各種假設)。一個明智的開發人員不會做這種事情,會打折其他人做這件事的可能性,並且會說Immutable是不可改變的,儘管理論上可能有一些瘋人可以改變它。

    0

    類的狀態仍然可以通過繼承進行修改。

    不變性的一個重要規則是讓你的類最終使你的類不能被繼承。

    查看本教程:How to create an immutable class in java

    +0

    感謝您的澄清,我已經相應地更新了答案。 –

    +0

    6年前沒有其他人說過嗎? –