首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Runnable::新的和新的Runnable()

Runnable::新的和新的Runnable()
EN

Stack Overflow用户
提问于 2019-01-07 10:15:01
回答 4查看 5.6K关注 0票数 63

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

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

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

代码语言:javascript
复制
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");
      }
  }
}

产出如下:

代码语言:javascript
复制
  R constructor runs
  -----------------------
  R constructor runs
  R.run runs

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

但是,如何才能成功地编译这个示例呢?

EN

回答 4

Stack Overflow用户

发布于 2019-01-07 10:18:34

您的run方法接受一个Runnable实例,这解释了为什么run(new R())R实现一起工作。

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

可以接受runR::new方法的版本可能如下所示(但这可能是不必要的复杂):

代码语言:javascript
复制
void run(Supplier<Runnable> r) {
    r.get().run();
}

它为什么要编译?

因为编译器可以利用构造函数调用生成一个Runnable,这相当于这个lambda表达式版本:

代码语言:javascript
复制
new ConstructorRefVsNew().run(() -> {
    new R(); //discarded result, but this is the run() body
});

同样的情况也适用于这些声明:

代码语言:javascript
复制
Runnable runnable = () -> new R();
new ConstructorRefVsNew().run(runnable);
Runnable runnable2 = R::new;
new ConstructorRefVsNew().run(runnable2);

但是,您可以注意到,使用R::new创建的R::new只在其run方法体中调用new R()

有效地使用方法引用来执行R#run可以使用这样的实例(但在本例中,您肯定更希望直接使用r实例):

代码语言:javascript
复制
R r = new R();
new ConstructorRefVsNew().run(r::run);
票数 57
EN

Stack Overflow用户

发布于 2019-01-07 10:23:11

第一个例子:

代码语言:javascript
复制
new ConstructorRefVsNew().run(R::new);

大致相当于:

代码语言:javascript
复制
new ConstructorRefVsNew().run( () -> {new R();} );

其结果是,您只创建一个R的实例,但不调用它的run方法。

票数 24
EN

Stack Overflow用户

发布于 2019-01-07 10:24:55

run方法需要一个Runnable

简单的例子是new R()。在这种情况下,您知道结果是一个R类型的对象。R本身是一个可运行的,它有一个run方法,这就是Java对它的看法。

但是当你通过R::new的时候,其他的事情正在发生。您告诉它的是创建一个与Runnable兼容的匿名对象,该对象的run方法运行您传递的操作。

您传递的操作不是Rrun方法。该操作是R的构造函数。因此,就像您传递了一个匿名类,如下所示:

代码语言:javascript
复制
new Runnable() {

     public void run() {
         new R();
     }
}

(并非所有细节都相同,但这是最近的“经典”Java构造)。

R::new,当被调用时,调用new R()。没有更多,没有更少。

票数 7
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/54072359

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档