它應該是所有領域,包括超級領域,有目的不可變的java類'final'爲了線程安全或足夠沒有修飾符方法嗎?最終字段和線程安全
假設我有一個非final字段的POJO,其中所有字段都是一些不可變類的類型。這個POJO有getters-setters,並且有一個構造函數來設置一些初始值。如果我通過敲除修飾符方法來擴展此POJO,從而使其不可變,擴展類將是線程安全的嗎?
它應該是所有領域,包括超級領域,有目的不可變的java類'final'爲了線程安全或足夠沒有修飾符方法嗎?最終字段和線程安全
假設我有一個非final字段的POJO,其中所有字段都是一些不可變類的類型。這個POJO有getters-setters,並且有一個構造函數來設置一些初始值。如果我通過敲除修飾符方法來擴展此POJO,從而使其不可變,擴展類將是線程安全的嗎?
爲了以線程安全的方式使用不帶final
字段的有效不可變對象,需要在初始化後使對象對其他線程可用時使用安全發佈習慣用法之一,否則這些線程可以看到部分初始化的對象狀態(從Java Concurrency in Practice):
- 初始化從靜態初始化的對象引用;
- 將引用存儲到易失性字段或AtomicReference中;
- 將引用存儲到正確構造的對象的最終字段中;或
- 將對其的引用存儲到由鎖正確保護的字段中。
聲明你的不可變對象final
發佈此限制的領域(即它保證,如果其他線程看到該對象的引用,他們也看到了完全初始化狀態,其final
場)。但是,通常情況下,它並不能保證其他線程在發佈時能夠看到對象的引用,因此您可能仍然需要使用安全發佈來確保它。
請注意,如果你的對象實現了接口,您可以使用Collections.unmodifiableList()
使用的方式,等:
class ImmutableFooWrapper implements IFoo {
private final IFoo delegate; // final provides safe publication automatically
public ImmutableFooWrapper(IFoo delegate) {
this.delegate = delegate;
}
...
}
public IFoo immutableFoo(IFoo foo) {
return new ImmutableFooWrapper(foo);
}
你是什麼意思*敲出修飾符方法*修飾符方法?拋出所有setter的異常?這會違反[Liskov替代原則](http://en.wikipedia.org/wiki/Liskov_substitution_principle)。但是,是的,這個類會**是線程安全的。 –
是的,拋出一個運行時異常或用一個空的主體覆蓋它們可能有一些日誌記錄。我知道這是違反LSP的。 – pcjuzer