代码之家  ›  专栏  ›  技术社区  ›  Marcono1234

将Runnable转换为供应商

  •  4
  • Marcono1234  · 技术社区  · 6 年前

    你怎么能 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);
    }
    

    useSupplier 对于 useRunnable ,例如,因为我不想复制代码。行为 使用供应商


    编辑:为了澄清,方法 使用供应商 使用供应商 是在某些上下文中从供应商处检索值,在我的例子中,它捕获(特定) RuntimeException

    public <T> T useSupplier(Supplier<T> supplier) {
        try {
            return supplier.get();
        }
        catch (RuntimeException runtimeException) {
            throw new MyException("Supplier threw exception", runtimeException);
        }
    }
    

    以下解决方案可以

    useSupplier(runnable);
    useSupplier(runnable::run);
    useSupplier((Supplier<Void>) runnable::run);
    

    我能想出的一个解决办法是创建一个新的 它返回一个任意值:

    useSupplier(() -> {
        runnable.run();
        return null;
    });
    

    runnable::run 还将创建新的lambda实例,因为它是有状态的,请参见 this answer .

    2 回复  |  直到 6 年前
        1
  •  8
  •   Sergey Belonozhko    6 年前

    在您的情况下,无法避免创建新对象。即使某个地方有一个方法将Runnable转换为Supplier,它也会在那里创建一个对象。 所以你的解决方案是有效的,你不会找到更好的。

    请注意,供应商应提供价值,而Runnable仅代表一种行为。它们用于不同的目的。因此,您需要将Runnable转换为供应商,这可能是设计问题的结果。

        2
  •  0
  •   Naman    6 年前

    看看你的设计,你可能只是在寻找 Consumer 它接受一个类型,只处理(使用)它而不返回值,也可以用来调整runnable,而不是 Supplier

    您可以使用以下内容:

    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);
    }
    

    如果要求使用

    public static void useRunnable(Runnable runnable) {
        useSupplier(() -> runnable); // the useSupplier returns the 'runnable' when this method is called
    }
    

    如注释中所述,现在当您调用 useRunnable 这个 useSupplier runnable ,但方法 void 因此,它被完全忽略了。

        3
  •  0
  •   M. Justin Marwan Alsabbagh    3 年前

    如果您发现自己在代码库中经常使用这种模式,那么创建一个 RunnableSupplier 类别:

    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));
    }
    

    null Supplier 特定类型的,只要它们允许空结果。如果你想强制执行,它总是一个 Supplier<Void> ,使其成为非泛型并实现 供应商<无效> 而不是 Supplier<T>