Consider the following code:
public class A {
public static void main(String[] args) {
Runnable test1 = ((I)(new I() {}))::test; // compiles OK
This is counter-intuitive. First let's simplify this a bit:
static interface Inter {
private void test() {
System.out.println("test");
}
}
public static void main(String[] args) {
((Inter) new Inter() {
}).hashCode();
}
This makes sense as you are calling the public hashCode
method, here is the (important part only) byte code for it:
public static void main(java.lang.String[]);
Code:
0: new #2 // class com/test/DeleteMe$1
3: dup
4: invokespecial #3 // Method com/test/DeleteMe$1."":()V
7: invokevirtual #4 // Method java/lang/Object.hashCode:()I
10: pop
11: return
Looks very sane to me. Now let's change that to calling test()
:
public static void main(String[] args) {
((Inter) new Inter() {
}).test();
}
The byte code for this:
invokestatic #4 // InterfaceMethod com/test/DeleteMe$Inter.access$000:(Lcom/test/DeleteMe$Inter;)V
Since private methods are not inherited, you are actually "going" to that method via the access$n
static synthetic method.