sha*_*pir 5 java evaluation lambda lazy-evaluation java-8
我编写了以下代码来Lazy<T>
在Java中进行模拟:
import java.util.function.Supplier;
public class Main {
@FunctionalInterface
interface Lazy<T> extends Supplier<T> {
Supplier<T> init();
public default T get() { return init().get(); }
}
static <U> Supplier<U> lazily(Lazy<U> lazy) { return lazy; }
static <T>Supplier<T> value(T value) { return ()->value; }
private static Lazy<Thing> thing = lazily(()->thing=value(new Thing()));
public static void main(String[] args) {
System.out.println("One");
Thing t = thing.get();
System.out.println("Three");
}
static class Thing{ Thing(){System.out.println("Two");}}
}
Run Code Online (Sandbox Code Playgroud)
但我得到以下警告:
"
(T)
Main中的值不能应用于(com.company.Main.Thing
)原因:没有类型变量T的实例存在,因此Supplier<T>
符合Lazy<Thing>
"
你能帮我找出问题所在吗?提前致谢!
value()
返回 a Supplier
,而thing
字段的类型为Lazy<Thing>
。您不能将 a 分配Supplier
给 a Lazy
(使用任何参数化),因为并非所有Supplier
实例都是Lazy
实例。
此外,尝试将lazily()
返回值(即 a Supplier
)分配给thing
,但出于同样的原因,这不会起作用。
我们可以将lazily
类型更改为Lazy
并删除该内联thing=
赋值(位于thing
初始值设定项表达式内)以使其编译:
static <U> Lazy<U> lazily(Lazy<U> lazy) { return lazy; }
static <T> Supplier<T> value(T value) { return ()->value; }
private static Lazy<Thing> thing = lazily(()->value(new Thing()));
Run Code Online (Sandbox Code Playgroud)
但我不确定这是否是你想要的。
如果您只是想要一种惰性行为,Supplier
它本身已经能够表现出惰性,因为get()
仅在请求时执行,而不是在Supplier
创建时执行。
如果你想要一个缓存逻辑(只计算一次,并且只计算需要的),你可以使用这样的东西:
public class CachingSupplier<T> implements Supplier<T> {
private final Supplier<T> supplier;
private T cachedValue;
private boolean computed = false;
public CachingSupplier(Supplier<T> supplier) {
this.supplier = supplier;
}
public T get() {
if (!computed) {
cachedValue = supplier.get();
computed = true;
}
return cachedValue;
}
}
Run Code Online (Sandbox Code Playgroud)
如果你想保证supplier.get()
最多被调用一次,你可以应用一些同步:
if (!computed) {
synchronized (this) {
if (!computed) {
cachedValue = supplier.get();
computed = true;
}
}
}
return cachedValue;
Run Code Online (Sandbox Code Playgroud)
这里,使用了双重检查锁定。
归档时间: |
|
查看次数: |
367 次 |
最近记录: |