【发布时间】:2019-02-10 15:39:31
【问题描述】:
如何将Runnable 转换为Supplier?
public <T> T useSupplier(Supplier<T> supplier) {
// Does something with supplier and returns supplied value
...
return value;
}
public void useRunnable(Runnable runnable) {
// Somehow convert runnable to Supplier
...
useSupplier(supplier);
}
这里我想为useRunnable重用方法useSupplier,例如因为我不想复制代码。 useSupplier 的行为与这个问题无关,假设它包装了抛出的异常,或者在同步块中使用供应商。
编辑:澄清一下,useSupplier 方法不与提供的值交互,它只是返回它。 useSupplier 的功能是在某些情况下从供应商那里检索值,在我的情况下,它捕获(特定)RuntimeExceptions,创建一个新异常作为原因并抛出它:
public <T> T useSupplier(Supplier<T> supplier) {
try {
return supplier.get();
}
catch (RuntimeException runtimeException) {
throw new MyException("Supplier threw exception", runtimeException);
}
}
以下解决方案不起作用(在 Java 8 中):
useSupplier(runnable);
useSupplier(runnable::run);
useSupplier((Supplier<Void>) runnable::run);
我能想到的一个解决方案是创建一个新的Supplier,它返回一个任意值:
useSupplier(() -> {
runnable.run();
return null;
});
有没有更小的解决方案?
编辑:正如 Holger 在 cmets 中指出的那样,使用 runnable::run 也会创建新的 lambda 实例,因为它是有状态的,另请参阅 this answer。
【问题讨论】:
-
run方法返回 void,因此您无法提供任何值。 -
对于
useRunnable我不关心返回值。正如我所写,useSupplier在同步块中使用了例如供应商,这也是我想要为useRunnable提供的。 -
考虑使用返回值的
Callable,而不是Runnable。 -
你能告诉我们更多关于
useRunnable(...)和useSupplier(...)的语义吗?从命名来看,它表明useRunnable(...)产生了一个新线程(至少对我而言)。 -
@Turing85 我正在捕获(特定的)
RuntimeExceptions 并以它们作为原因抛出新异常。所以我不关心供应商返回的价值,我只返回它。
标签: java java-8 functional-interface