java - Runnable::new 与新的 Runnable()

标签 java java-8 runnable constructor-reference

为什么下面的第一个例子不起作用?

  • run(R::new); 方法 R.run 未被调用。
  • run(new R()); 方法 R.run 调用。

这两个示例都是可编译的。

public class ConstructorRefVsNew {

  public static void main(String[] args) {
      new ConstructorRefVsNew().run(R::new);
      System.out.println("-----------------------");
      new ConstructorRefVsNew().run(new R());
  }

  void run(Runnable r) {
      r.run();
  }

  static class R implements Runnable {

      R() {
          System.out.println("R constructor runs");
      }

      @Override
      public void run() {
          System.out.println("R.run runs");
      }
  }
}

输出是:

  R constructor runs
  -----------------------
  R constructor runs
  R.run runs

在第一个例子中,调用了 R 构造函数,它返回 lambda(不是对象):

但那怎么可能编译成功呢?

最佳答案

您的run方法采用 Runnable 实例,这就解释了为什么 run(new R())R 一起使用实现。

R::new不等于 new R() .它可以适合 Supplier<Runnable> 的签名(或类似的功能接口(interface)),但 R::new不能用作 Runnable 使用您的 R 实现类。

您的 run 的一个版本可以采取的方法R::new可能看起来像这样(但这会不必要地复杂):

void run(Supplier<Runnable> r) {
    r.get().run();
}

Why does it compile?

因为编译器可以生成 Runnable 在构造函数调用之外,这将等效于这个 lambda 表达式版本:

new ConstructorRefVsNew().run(() -> {
    new R(); //discarded result, but this is the run() body
});

这同样适用于这些陈述:

Runnable runnable = () -> new R();
new ConstructorRefVsNew().run(runnable);
Runnable runnable2 = R::new;
new ConstructorRefVsNew().run(runnable2);

但是,如您所见, Runnable 使用 R::new 创建只是调用new R()在其run方法体。


有效地使用方法引用来执行 R#run可以使用这样的实例(但在这种情况下,您肯定更愿意直接使用 r 实例):

R r = new R();
new ConstructorRefVsNew().run(r::run);

关于java - Runnable::new 与新的 Runnable(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54072359/

相关文章:

java - 尝试从 JSONArray 中检索 JSONObject 时返回 null?

java - 如何在数组JAVA中存储递归函数值

java - 创建一个生成另一个给定函数的 x 和 y 值的方法

java - 如何决定runable的顺序

通过 REST Json 的 JavaFX2 客户端-服务器

java - jFreeChart。组合图表错误内子图的高度?

java - 重构带有副作用的 for 循环以进行流式传输

Java 8 : Getting a property from a List of a List

java - 使用 Java 8 Stream API 查找枚举值

java - 如何使运行代码能够访问触发器中提供的变量的可运行