對於商業決策應用程序,我遇到了很多情況,我必須緩存一個昂貴的值,並使用延遲初始化。所以我利用泛型和供應商lambda來封裝一個懶惰的初始化。在懶惰的初始化供應商中引用「this」?
import java.util.function.Supplier;
public final class LazyProperty<T> {
private final Supplier<T> supplier;
private volatile T value;
private LazyProperty(Supplier<T> supplier) {
this.supplier = supplier;
}
public T get() {
if (value == null) {
synchronized(this) {
if (value == null) {
value = supplier.get();
}
}
}
return value;
}
public static <T> LazyProperty<T> forSupplier(Supplier<T> supplier) {
return new LazyProperty<T>(supplier);
}
}
但我希望能夠在我不能初始化屬性的對象被創建後,直到情況下也用這個,因爲在創建後它的對象只能算這個屬性(通常需要自身或其他對象的上下文)。但是,這通常需要在供應商功能中參考this
。
public class MyClass {
private final LazyProperty<BigDecimal> expensiveVal =
LazyProperty.forSupplier(() -> calculateExpensiveVal(this));
public BigDecimal getExpensiveVal() {
return expensiveVal.get();
}
}
只要我能保證MyClass
構造(通過getExpensiveVal()
方法)後LazyProperty的get()
功能只叫,不應該是由於供應商的this
參考任何部分建設問題,正確的?
我不一定看到這個問題,因爲'this'是指'MyClass'而不是lambda。你是否遇到過這個問題,還是擔心它在概念上不合理? – Makoto
不,我沒有問題,是的,我只是關心這在概念上是不健全的。我一直認爲在初始化或構造中引用'this'是有風險的,因爲它可以暴露一個部分構造的對象。但對於函數式編程,任何包含'this'引用的lambda表達式(指MyClass)都是無害的,除非它們在構造時被執行。 – tmn
是的;這就是爲什麼我在這裏看不到問題。你在任何地方都沒有在構造函數中使用'expensiveVal'字段,所以我不相信你會遇到一個問題。您可能會對類型安全性感興趣,因爲您必須確保'calculateExpensiveVal'將使用您想要的正確類型。 – Makoto