Reputation:
I'm confused with method references. Consider the following script.
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();
}
}
So it seems that:
i::m
does not behave like i.m()
...So my questions are:
Are method references using reflection? And why they do only once?
Upvotes: 0
Views: 203
Reputation: 692023
If you think about how this code would be written without method references, but with classes and objects, it all makes sense:
r = i::m;
is basically equivalent to
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);
So, if you assign another value to i
after the IRunnable has been constructed, the IRunnable continues referencing the previous value, and calling its run()
method again will still call the previous i
's method.
Upvotes: 2