0

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:

  • The compiler cannot inline method references because they are polymorphic. They are not resolved at compilation time, but at runtime.
  • But i::m does not behave like i.m()...

So my questions are:

Are method references using reflection? And why they do only once?

4

1 回答 1

2

如果您考虑如何在没有方法引用但使用类和对象的情况下编写此代码,这一切都是有道理的:

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);

因此,如果您i在构造 IRunnable 之后为其分配另一个值,则 IRunnable 会继续引用先前的值,并且run()再次调用其方法仍将调用先前i的方法。

于 2015-03-13T20:37:18.613 回答