如果期望Runnable Instance,方法引用运算符如何被接受?

Chi*_*tan 4 java multithreading java-8 method-reference

我最近遇到了下面的示例代码,其中方法引用运算符用于引用方法调用.有两个问题,我正在寻找答案1.执行方法,其中调用它期望Runnable类.这段代码编译文件并没有给出错误原因(App类不是Runnable)?2.如果我替换executorService.execute(app :: someMethod); with executorService.execute(app.someMethod()); 它给出了编译错误的原因?

public class Temp {

private static final Logger LOGGER = LoggerFactory.getLogger(Temp.class);

/**
 * @param args the command line arguments - not used
 */`enter code here`
public static void main(String... args) {
    final App app = new App();
    ExecutorService executorService = Executors.newFixedThreadPool(3);
    for (int i = 0; i < 3; i++) {
        executorService.execute(app::someMethod);
    }
    executorService.shutdown();
    try {
        executorService.awaitTermination(10, TimeUnit.SECONDS);
    } catch (InterruptedException ie) {
        LOGGER.error("ERROR: Waiting on executor service shutdown!");
    }
}

}
class App {
     public void someMethod() {
           // Some logic
     }
}
Run Code Online (Sandbox Code Playgroud)

Fed*_*ner 6

ExecutorService.execute期望一个类型的参数Runnable.

首先回答你的上一个问题... App.someMethod()是一种void方法(即它不返回任何东西).由于app.someMethod()返回类型是void,并且由于void类型无法分配给类型的变量或方法参数Runnable,因此您将收到编译错误.

现在,关于你的第一个问题...... Runnable接口是一个功能接口,因为它声明了一个抽象方法(SAM):

@FunctionalInterface
public interface Runnable {

    void run();
}
Run Code Online (Sandbox Code Playgroud)

这里的SAM是void run(),它没有接收任何参数,是一种void方法.

现在,所述方法参考app::someMethod指定void someMethod()所述的方法App类,其签名相匹配,所述的一个run所述的方法Runnable接口(通过匹配我的意思是,这两种方法返回类型是void,并且也不它们中的一个接收到的任何参数).

因此,当您将app::someMethod方法引用作为参数传递给executorService.execute方法时,编译器会安全地其转换为Runnable实例.


编辑:当用户@MC Emperor在注释中突出显示时,类的someMethod方法可能返回一些东西(即它不一定是方法).在这种情况下,如规范所述(参见JLS§15.27.3,感谢链接!),返回值将被简单地丢弃.Appvoid

这是因为在Java中,方法返回的值可以被丢弃,方法引用(以及lambda表达式)也会遵循这种行为.

  • 请注意,`app :: someMethod`*可能*返回一些内容.如果是,则将其丢弃,参见[JLS§15.27.3](https://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.27.3) . (3认同)
  • @MC皇帝.这是一个非常有价值的评论!重要的是要指出在这种情况下,返回类型被丢弃,这可以防止我们在app.someMethod()的情况下收到错误. (2认同)