java - 如何在需要 Runnable Instance 的地方接受方法引用运算符?
问题描述
我最近遇到了下面的示例代码,其中方法引用运算符用于引用方法调用。有 2 个问题我正在寻找答案 1. 调用它的执行方法需要 Runnable 类。此代码编译文件并且没有给出错误为什么(App 类不是 Runnable)?2.如果我替换 executorService.execute(app::someMethod); 与 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
}
}
解决方案
ExecutorService.execute
需要一个类型的参数Runnable
。
首先回答你的最后一个问题......App.someMethod()
是一种void
方法(即它不返回任何东西)。由于app.someMethod()
的返回类型是void
,并且由于void
无法将类型分配给 type 的变量或方法参数Runnable
,因此会出现编译错误。
现在,至于你的第一个问题......Runnable
接口是一个功能接口,因为它声明了一个抽象方法(SAM):
@FunctionalInterface
public interface Runnable {
void run();
}
这里的 SAM 是void run()
,它不接收任何参数并且是一种void
方法。
现在,方法引用app::someMethod
的目标是类的void someMethod()
方法App
,其签名与接口的run
方法之一匹配Runnable
(通过匹配我的意思是两个方法的返回类型都是void
,并且它们都没有接收任何参数)。
因此,当您将app::someMethod
方法引用作为参数传递给executorService.execute
方法时,编译器会安全地将其转换为Runnable
实例。
编辑:正如用户@MC Emperor 在评论中强调的那样,类的someMethod
方法可能会返回一些东西(即它不一定是方法)。在这种情况下,如规范所述(请参阅JLS § 15.27.3,感谢您的链接!),返回值将被简单地丢弃。App
void
这是因为在 Java 中,方法返回的值可以被丢弃,并且方法引用(以及 lambda 表达式)尊重这种行为。
推荐阅读
- git - 如何在github中自动保留特定数量的最新标签?
- javascript - TypeError:无法读取未定义的属性(读取“地图”)Table.render
- python - 用另一个列表遍历一个列表
- python - python beautifulsoup4 selenium ChromeDriverManager [网页爬取到最后都不起作用]
- regex - 查找模式和字符直到空格,并将捕获的模式移动到行尾 sed
- r - 在R中找到另一个日期之前的最早日期?
- mysql - SQL如何将整数值四舍五入到小数点后2位
- pdfbox - PDFBox:检测给定页面中突出显示的文本
- mongodb - 如何在 mongodb 中提高 $in 的性能?
- csv - 使用 spark-sql cli 将 csv 数据直接加载到 parquet 表中