use*_*245 61 java runnable java-8 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");
}
}
}
Run Code Online (Sandbox Code Playgroud)
输出是:
R constructor runs
-----------------------
R constructor runs
R.run runs
Run Code Online (Sandbox Code Playgroud)
在第一个示例中,R调用构造函数,它返回lambda(不是对象):
但是,如何成功编译示例怎么可能呢?
ern*_*t_k 56
您的run方法需要一个Runnable实例,这解释了为什么run(new R())适用于R实现.
R::new不等于new R().它可以适合Supplier<Runnable>(或类似的功能接口)的签名,但R::new不能用作Runnable您的R类实现.
您run可以采用的方法版本R::new可能如下所示(但这会不必要地复杂):
void run(Supplier<Runnable> r) {
r.get().run();
}
Run Code Online (Sandbox Code Playgroud)
为什么编译?
因为编译器可以进行Runnable构造函数调用,这相当于这个lambda表达式版本:
new ConstructorRefVsNew().run(() -> {
new R(); //discarded result, but this is the run() body
});
Run Code Online (Sandbox Code Playgroud)
这些陈述同样适用:
Runnable runnable = () -> new R();
new ConstructorRefVsNew().run(runnable);
Runnable runnable2 = R::new;
new ConstructorRefVsNew().run(runnable2);
Run Code Online (Sandbox Code Playgroud)
但是,正如您所注意到的,Runnable创建的R::new只是调用new R()其run方法体.
对执行方法引用的有效使用R#run可以使用像这样的实例(但r在这种情况下,你肯定会直接使用实例):
R r = new R();
new ConstructorRefVsNew().run(r::run);
Run Code Online (Sandbox Code Playgroud)
Hen*_*nry 23
第一个例子:
new ConstructorRefVsNew().run(R::new);
Run Code Online (Sandbox Code Playgroud)
或多或少相当于:
new ConstructorRefVsNew().run( () -> {new R();} );
Run Code Online (Sandbox Code Playgroud)
效果是您只需创建R的实例,但不要调用其run方法.
And*_*lko 10
比较两个电话:
((Runnable)() -> new R()).run();
new R().run();
Run Code Online (Sandbox Code Playgroud)
通过((Runnable)() -> new R())或((Runnable) R::new),您创建一个新的Runnable,什么也不做1.
通过new R(),您创建的实例R类,其中的run方法是明确的.
1实际上,它创建的对象R对执行没有影响.
我想在不修改main方法的情况下同样处理2个调用.我们将需要重载run(Runnable)使用run(Supplier<Runnable>).
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();
}
void run(Supplier<Runnable> s) {
run(s.get());
}
static class R implements Runnable { ... }
}
Run Code Online (Sandbox Code Playgroud)
该run方法需要一个Runnable.
容易的情况是new R().在这种情况下,您知道结果是类型的对象R.R它本身是一个可运行的,它有一个run方法,这就是Java看到它的方式.
但是当你传递R::new其他东西时正在发生.你告诉它的是创建一个与a 方法兼容的匿名对象,Runnable该run方法运行你传递它的操作.
你通过它的操作不是R的run方法.操作是的结构R.因此,就像你已经传递了一个匿名类,如:
new Runnable() {
public void run() {
new R();
}
}
Run Code Online (Sandbox Code Playgroud)
(并非所有细节都相同,但这是最接近的"经典"Java构造).
R::new,当被叫时,打电话new R().没有更多,没有更少.
| 归档时间: |
|
| 查看次数: |
4354 次 |
| 最近记录: |