2010-05-25 100 views
5

我希望能夠指定一個對象的成員變量是不可變的,一旦對象已被「初始化」,這對我來說意味着它被注入任何依賴關係後,並已執行任何其他初始化操作,它只能在DI之後執行。依賴注入後的不變性,初始化

是否有語言滿足我的興趣 - 以這種方式正式化DI,初始化和支持不變性?也許讓他們成爲語言的一部分是愚蠢的;也許不會。我不確定。

今天我用Java編程,但我幾乎不能使用「final」,因爲這些階段發生在構造函數完成執行之後。有關如何獲得我想要的Java的建議?我想我可以讓我的對象實現一個基類,以便這些階段在構造函數完成之前發生,或者使用方面來完成。

想法?

回答

3

我猜這取決於你想要的不變性。如果你想要保證線程安全(所有的東西都必須聲明爲最終的,包括依賴),那麼我認爲工廠,構建器或構造器注入是你唯一的選擇。

如果你只是想要狀態的不變性,那麼聲明狀態變量最終應該是足夠的。即使不可變的String類在其實現中也有一個可變字段(哈希碼值的緩存)。只要你的代碼確保一個實例在沒有注入的情況下不可用,所有的都應該是好的。

+0

我只是想清楚哪些成員是可變的,哪些不是。 奇怪,但我從來沒有想過如何setter注入不可兼容的不變狀態。那麼,當我寫這個問題的時候,我沒有想過,至少:-) – Ladlestein 2010-05-26 02:06:48

0

在Java中,如果你正在使用mutator方法來進行設置,那麼在初始化對象時添加邏輯以防止更改會很便宜(儘管在我眼中也很醜)。

public void setMyProperty(String newValue) { 
    checkInitialized(); 
    myProperty = newValue; 
} 

public void checkInitialized() { 
    if (initialized) { 
     throw new IllegalStateException("Setter called after initialization"); 
    } 
} 

儘管這是給予動態檢查。它不會給你任何你已經擁有的靜態反饋。

4

有產生不可變對象的方式主要有兩種:

  1. 使用Builder /工廠模式 - 生成器可以是可變的,但它創建的對象是不可改變的,通常與最終實現的領域。你也可以將兩者結合起來,因此對象本身被用來構建新的實例,通常通過改變單獨新實例上的狀態的「變種」方法。 Spring的FactoryBean就是一個例子。

  2. 創建一個MutableObject子類,它維護一個可變狀態標誌。所有的mutators在進行任何更改之前都會檢查可變狀態 - 如果該對象已設置爲不可變,則該檢查會引發異常,否則更改將繼續。

第一種方法完全以Spring爲中心,因爲它需要實現彈簧專用接口。您可以通過bean上的factory-method/factory-bean屬性來創建常規bean的工廠bean,這會從代碼中刪除彈簧依賴項。

使用第二種方法對彈簧特別有用。您可以指示spring在bean初始化後調用方法,例如密封物體的密封()使其不可變。或者,你可以實現一個小的BeanFactoryPostProcessor來自動完成,而不必記得設置init-method =「seal」。在每個不可變的bean上。

+0

您的回答很有幫助;我已經選擇了另一個,因爲它說「構造函數注入」,這對我來說更好一些。 – Ladlestein 2010-05-26 01:52:33

+0

我想使用「最終」或者用另一種語言,任何機制表示並強制不變。在Java中,Builder對我有幫助嗎?是不是使用必要的構造函數注入來使用final? – Ladlestein 2010-05-26 02:10:42

+0

構建器可以使用setter注入,並使用構造函數注入產生對象。 C.F. Spring中的大多數FactoryBean實現 - 它們使用setter注入進行配置。 – mdma 2010-05-26 09:58:40

1

在Java中,您可以使用builder在其構造函數中初始化一個不可變的對象,因此您會避開setter。

如果您使用Scala,但不可變性爲the default

+0

正如我上面所說的,Builder是如何幫助的,在我看來Builder並不相關,除非我使用構造函數注入。 – Ladlestein 2010-05-26 02:11:27

+0

確切的說,這就是爲什麼我說「避開二傳手」。 – 2010-05-26 10:29:10

0

要指定一個類是不可變的,可以使用@Immutable註釋。

您可以看到Javadoc here

這適用於Eclipse中的Findbugs插件。

@Alexander:

據我瞭解他,他問如何指定一個類是不可變的。不是如何寫一個不可變的類。此註釋可以爲您提供工具支持,以驗證您的班級中沒有您聲稱是不可變的錯誤。

距離的Javadoc片段:

必要性。這意味着所有 公共領域是最終的,並且所有 公開的最終參考字段參考 其他不可變對象

+0

-1。啊哈!有沒有'@ NoBugs'註釋? :) – 2010-05-25 20:42:39

+1

公平點。 Downvote刪除。 – 2010-05-25 21:05:14

相關問題