Java 具有可变参数的方法,执行操作并打印已知结果

Java method with varargs that executes actions and prints known result

是否可以在 Java 中创建类似于此 execute 方法的方法:

public void execute(Runnable... mrs) {
    for (Runnable mr : mrs) {
        mr.run();
        // should print some expected string here
    }
}

public void sleep(int seconds) {
    try {
        Thread.sleep(1000 * seconds);
    } catch (InterruptedException ex) {
        log.error("Error occured", ex);
    }
}

public void customExecute() {
    execute(() -> sleep(1), () -> sleep(2));
}

但在执行每个操作后,它应该打印传递的 String 参数,并且(问题的关键时刻)它应该支持一行用法 - 类似于:

execute(("Action 1 passed") -> someAction(), ("Other action passed") -> otherAction());

Java 没有将键值对传递给方法的特殊语法。我看到两种可能的解决方案。

1。创建附加对象:

static class NamedRunnable implements Runnable {
    Runnable r;
    String title;
    
    public NamedRunnable(String title, Runnable r) {
        this.title = title;
        this.r = r;
    }

    @Override
    public void run() {
        r.run();
    }
    
    @Override
    public String toString() {
        return title;
    }
}

public void execute(NamedRunnable... mrs) {
    for (NamedRunnable mr : mrs) {
        mr.run();
        System.out.println(mr+" completed");
    }
}

public void customExecute() {
    execute(new NamedRunnable("Action 1 passed", () -> sleep(1)), 
            new NamedRunnable("Other action passed", () -> sleep(2)));
}

面向对象,但不是很短

2。用不同数量的参数声明几个 execute 方法。

public void execute(String t1, Runnable r1) {
    execute(new NamedRunnable(t1, r1));
}

public void execute(String t1, Runnable r1, String t2, Runnable r2) {
    execute(new NamedRunnable(t1, r1), 
            new NamedRunnable(t2, r2));
}

public void execute(String t1, Runnable r1, String t2, Runnable r2, 
        String t3, Runnable r3) {
    execute(new NamedRunnable(t1, r1), 
            new NamedRunnable(t2, r2),
            new NamedRunnable(t3, r3));
}

// continue if you need more

public void customExecute() {
    execute("Action 1 passed", () -> sleep(1), "Other action passed", () -> sleep(2));
}

这里的调用看起来更简洁,但它需要更多的“库”代码。

您可以使用构建器模式的变体来做到这一点:

public interface Step {
    void doIt(String msg, Runnable r);
    default Step then(String msg, Runnable r) {
        doIt(msg, r);
        return this;
    }
}
public static Step execute(String msg, Runnable r) {
    Step s=(m,x)-> {
        x.run();
        System.out.println(msg);
    };
    return s.then(msg, r);
}

那你就可以像

一样使用它
execute("Action 1 passed", () -> someAction())
  .then("Other action passed", () -> otherAction());

随意扩展

execute("Action 1 passed", () -> someAction())
  .then("Other action passed", () -> otherAction())
  .then("NextAction passed", () -> nextAction())
  .then("and nextAction passed again", () -> nextAction()) ;

它也很容易适应其他执行策略,例如

static ExecutorService es=Executors.newSingleThreadExecutor();
public static Step executeInBackground(String msg, Runnable r) {
    Step s=(m,x)-> es.execute(()-> execute(m, x));
    return s.then(msg, r);
}

调用方稍作改动即可使用:

executeInBackground("Action 1 passed", () -> someAction())
  .then("Other action passed", () -> otherAction())
  .then("NextAction passed", () -> nextAction())
  .then("and nextAction passed again", () -> nextAction());

这是一个使用可变参数和高阶函数的变体。它比 Holger 的更简单(但也更不通用)。但是,如果您只想在执行 Runnable.

后打印一个字符串,这可能就足够了

这个想法是有一个函数,它通过获取现有的并在 运行 之后打印一个字符串来创建一个新的 Runnable 它:

static Runnable runPrint(Runnable r, String msg) {
    return () -> {
        r.run();
        System.out.println(msg);
    };
}

然后您只需将其中几个传递给基于可变参数的 execute 方法:

    execute(runPrint(() -> sleep(1), "first"),
            runPrint(() -> sleep(2), "second"),
            runPrint(() -> sleep(3), "third"));