jeudi 2 février 2017

Lambda accessibility to private methods

I'm confused with following situation.

Consider two packages a and b with following classes:

1) MethodInvoker just invokes call() on given object:

package b;
import java.util.concurrent.Callable;
public class MethodInvoker {
    public static void invoke(Callable r) throws Exception {
        r.call();
    }
}

2)

package a;
import b.MethodInvoker;
import java.lang.reflect.Method;
import java.util.concurrent.Callable;
public class Test {

    private static Void method() {
        System.out.println("OK");
        return null;
    }

    public static void main(String[] args) throws Exception {
        Method method = Test.class.getDeclaredMethod("method");
        method.invoke(null);        // ok

        // TEST 1
        MethodInvoker.invoke(() -> {
            return method.invoke(null);  // ok (hmm....
        });

        // TEST 2
        MethodInvoker.invoke(new Callable() {
            @Override
            public Object call() {
                return method();        // ok (hm...???
            }
        });

        // TEST 3
        MethodInvoker.invoke(new Callable() {
            @Override
            public Object call() throws Exception {
                return method.invoke(null); // throws IllegalAccessException, why???

            }
        });
    }
}

I explicitly made method() private to test how it can be invoked outside Test class scope. And I'm generally confused about all 3 cases, because I find them controversial. I generally would expect that all of them should work in same way. As minimum I would expect that if TEST 3 throws IllegalAccessException, so and TEST 2 should do the same. But TEST 2 works fine!

Could somebody give strict explanation according to JLS why each of these cases work as it works?





Aucun commentaire:

Enregistrer un commentaire