Для приложений бизнес-решений я сталкиваюсь с множеством случаев, когда я должен кэшировать дорогостоящее значение с ленивой инициализацией. Поэтому я использовал дженерики и лямбда Поставщика, чтобы инкапсулировать ленивую инициализацию.Ссылка «это» в ленивом поставщике инициализации?
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();
}
}
Пока я могу гарантировать get()
функция LazyProperty, называется только после того, как MyClass
построен (с помощью метода getExpensiveVal()
), не должно быть никаких частичных вопросов строительства в связи с this
ссылкой на поставщика, корректные ?
Я не обязательно вижу проблему с этим, так как 'this' относится к' MyClass', а не лямбда. Вы сталкивались с проблемой, или вы были обеспокоены тем, что это было концептуально необоснованным? – Makoto
Нет, у меня не было никаких проблем, и да, я просто был обеспокоен тем, что это было концептуально необоснованным. Я всегда читал, что ссылки на 'this' при инициализации или построении являются рискованными, потому что они могут выставлять частично сконструированный объект. Но с функциональным программированием имеет смысл, что любые lambdas, содержащие ссылки на 'this' (ссылаясь на MyClass), являются безобидными, если они не выполняются при построении. – tmn
Да; вот почему я не вижу здесь проблемы. Вы не используете поле 'дорогоеVal' в конструкторе в любом месте, поэтому я не верю, что вы столкнетесь с проблемой. У вас может быть интересное время с безопасностью типа, так как вы должны убедиться, что 'calculateExpensiveVal' будет использовать нужный вам тип. – Makoto