将 Runnable 转换为 Supplier
Convert Runnable to Supplier
如何将 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
不与提供的值交互,它只是 returns 它。 useSupplier
的功能是在某些上下文中从供应商检索值,在我的例子中它捕获(特定的)RuntimeException
s,创建一个新的异常作为原因并抛出它:
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
其中 returns 一个任意值:
useSupplier(() -> {
runnable.run();
return null;
});
有没有更小的解决方案?
编辑:正如 Holger 在评论中指出的那样,使用 runnable::run
也将创建新的 lambda 实例,因为它是有状态的,另请参见 this answer。
在您的情况下,您无法避免创建新对象。即使某处存在将 Runnable 转换为 Supplier 的方法,它也会在那里创建一个对象。
所以你的解决方案是有效的,你不会找到更好的。
注意Supplier需要提供值,而Runnable只是代表一个action。它们用于不同的目的。因此,您需要将 Runnable 转换为 Supplier 可能是涉及设计问题的结果。
看看你的设计,你可能只是在寻找 Consumer
它接受一个类型并且只处理(消耗)它而没有 return 一个值并且也可以用来适应一个可运行的,而不是 Supplier
,另一方面,它预期 return (提供)一个值 post-processing.
你可以使用类似的东西:
private static <T> void useConsumer(Consumer<T> consumer, T val) {
// Does something with supplier and returns supplied value
consumer.accept(val);
}
public static <T> void useRunnable(Runnable runnable) {
useConsumer(Runnable::run, runnable);
}
如果要求肯定要使用 Supplier
,那么您可以调用该方法:
public static void useRunnable(Runnable runnable) {
useSupplier(() -> runnable); // the useSupplier returns the 'runnable' when this method is called
}
如评论中所述,现在当您调用 useRunnable
时,useSupplier
将 return 与 runnable
相同,但方法 useRunnable
是void
再次被忽略。
如果您发现自己在代码库中大量使用此模式,可能值得创建一个 RunnableSupplier
class:
public class RunnableSupplier<T> implements Supplier<T> {
private final Runnable runnable;
public RunnableSupplier(Runnable runnable) {
this.runnable = runnable;
}
@Override
public T get() {
runnable.run();
return null;
}
}
public void useRunnable(Runnable runnable) {
useSupplier(new RunnableSupplier(runnable));
}
我已将此 class 设为通用,因为 null
可以为所有通用类型的供应商返回。这使得在需要特定类型的 Supplier
s 的库方法中使用成为可能,只要它们允许空结果。如果你想强制它始终是 Supplier<Void>
,可以直接将其设为非泛型并实现 Supplier<Void>
而不是 Supplier<T>
.
如何将 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
不与提供的值交互,它只是 returns 它。 useSupplier
的功能是在某些上下文中从供应商检索值,在我的例子中它捕获(特定的)RuntimeException
s,创建一个新的异常作为原因并抛出它:
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
其中 returns 一个任意值:
useSupplier(() -> {
runnable.run();
return null;
});
有没有更小的解决方案?
编辑:正如 Holger 在评论中指出的那样,使用 runnable::run
也将创建新的 lambda 实例,因为它是有状态的,另请参见 this answer。
在您的情况下,您无法避免创建新对象。即使某处存在将 Runnable 转换为 Supplier 的方法,它也会在那里创建一个对象。 所以你的解决方案是有效的,你不会找到更好的。
注意Supplier需要提供值,而Runnable只是代表一个action。它们用于不同的目的。因此,您需要将 Runnable 转换为 Supplier 可能是涉及设计问题的结果。
看看你的设计,你可能只是在寻找 Consumer
它接受一个类型并且只处理(消耗)它而没有 return 一个值并且也可以用来适应一个可运行的,而不是 Supplier
,另一方面,它预期 return (提供)一个值 post-processing.
你可以使用类似的东西:
private static <T> void useConsumer(Consumer<T> consumer, T val) {
// Does something with supplier and returns supplied value
consumer.accept(val);
}
public static <T> void useRunnable(Runnable runnable) {
useConsumer(Runnable::run, runnable);
}
如果要求肯定要使用 Supplier
,那么您可以调用该方法:
public static void useRunnable(Runnable runnable) {
useSupplier(() -> runnable); // the useSupplier returns the 'runnable' when this method is called
}
如评论中所述,现在当您调用 useRunnable
时,useSupplier
将 return 与 runnable
相同,但方法 useRunnable
是void
再次被忽略。
如果您发现自己在代码库中大量使用此模式,可能值得创建一个 RunnableSupplier
class:
public class RunnableSupplier<T> implements Supplier<T> {
private final Runnable runnable;
public RunnableSupplier(Runnable runnable) {
this.runnable = runnable;
}
@Override
public T get() {
runnable.run();
return null;
}
}
public void useRunnable(Runnable runnable) {
useSupplier(new RunnableSupplier(runnable));
}
我已将此 class 设为通用,因为 null
可以为所有通用类型的供应商返回。这使得在需要特定类型的 Supplier
s 的库方法中使用成为可能,只要它们允许空结果。如果你想强制它始终是 Supplier<Void>
,可以直接将其设为非泛型并实现 Supplier<Void>
而不是 Supplier<T>
.