Java 8 个方法引用 - 仅取消引用一次?
Java 8 method references - dereferenced only once?
我对方法引用感到困惑。考虑以下脚本。
public class Main {
static interface I {
void m();
}
static class A implements I {
@Override
public void m() {
System.out.println("A");
}
}
static class B implements I {
@Override
public void m() {
System.out.println("B");
}
}
public static void main(String[] args) {
A a = new A(); B b = new B();
I i; Runnable r;
i = a;
r = i::m; // static reference? might infere class
r.run(); // prints "A"
run(i); // also prints "A"
i = b;
r.run(); // prints "A" instead of "B"!
run(i); // prints "B"
r = i::m;
r.run(); // now prints "B"
run(i); // also prints "B"
}
public static void run(I i) {
Runnable r = i::m; // dynamic reference, cannot infere class
r.run();
}
}
这么看来:
- 编译器无法内联方法引用,因为它们是多态的。它们不会在编译时解析,而是在 运行时.
- 但是
i::m
不像 i.m()
...
所以我的问题是:
方法引用是否使用反射?为什么他们 只做一次 ?
如果您考虑如何在没有方法引用但有 类 和对象的情况下编写这段代码,这一切都是有道理的:
r = i::m;
基本等同于
private class IRunnable implements Runnable {
private I i;
public IRunnable(I i) {
this.i = i;
}
@Override
public void run() {
i.m();
}
}
Runnable r = new IRunnable(i);
所以,如果在构造IRunnable后给i
赋另一个值,IRunnable会继续引用之前的值,再次调用它的run()
方法还是会调用之前的i
的方法。
我对方法引用感到困惑。考虑以下脚本。
public class Main {
static interface I {
void m();
}
static class A implements I {
@Override
public void m() {
System.out.println("A");
}
}
static class B implements I {
@Override
public void m() {
System.out.println("B");
}
}
public static void main(String[] args) {
A a = new A(); B b = new B();
I i; Runnable r;
i = a;
r = i::m; // static reference? might infere class
r.run(); // prints "A"
run(i); // also prints "A"
i = b;
r.run(); // prints "A" instead of "B"!
run(i); // prints "B"
r = i::m;
r.run(); // now prints "B"
run(i); // also prints "B"
}
public static void run(I i) {
Runnable r = i::m; // dynamic reference, cannot infere class
r.run();
}
}
这么看来:
- 编译器无法内联方法引用,因为它们是多态的。它们不会在编译时解析,而是在 运行时.
- 但是
i::m
不像i.m()
...
所以我的问题是:
方法引用是否使用反射?为什么他们 只做一次 ?
如果您考虑如何在没有方法引用但有 类 和对象的情况下编写这段代码,这一切都是有道理的:
r = i::m;
基本等同于
private class IRunnable implements Runnable {
private I i;
public IRunnable(I i) {
this.i = i;
}
@Override
public void run() {
i.m();
}
}
Runnable r = new IRunnable(i);
所以,如果在构造IRunnable后给i
赋另一个值,IRunnable会继续引用之前的值,再次调用它的run()
方法还是会调用之前的i
的方法。