On Jan 2, 2017, at 11:33 PM, Alan Bateman <alan.bate...@oracle.com> wrote:
> 
> On 03/01/2017 07:17, Remi Forax wrote:
> 
>> I do not think that the workaround to create a Lookup object by reflection 
>> works with 9 given that java.lang.invoke is not declared as an open package.
>> 
>> John Rose has proposed to add a method to get a private Lookup object 
>> through sun.misc.Unsafe but as far as i know, this proposal goes nowhere.
>> 
> I think we got a good place with MethodHandles.privateLookupIn. It's not 
> going to allow you get a Lookup with private access to types in core modules 
> such as java.base but it may be useful for some cases.

+1

As of JDK-8130227, it is possible to use Lookup.findSpecial to gain access to 
interface default methods.

See below for an example.

— John

/*
  $ javac InvokeDefault.java && java -ea InvokeDefault
  override foo on an OverridesDefault
  default foo on an OverridesDefault
  default foo on an OverridesDefault
  $ java version "9-ea"
  Java(TM) SE Runtime Environment (build 9-ea+131)
  Java HotSpot(TM) 64-Bit Server VM (build 9-ea+131, mixed mode)
*/

import java.lang.invoke.*;
import static java.lang.invoke.MethodHandles.*;
import static java.lang.invoke.MethodType.*;

interface HasDefault {
    default String foo() { return "default foo on "+this; }
}
public class InvokeDefault {
    private static class OverridesDefault implements HasDefault {
        public String foo() { return "override foo on "+this; }
        public String toString() { return "an OverridesDefault"; }
    }
    public static void main(String... av) throws Throwable {
        HasDefault obj = new OverridesDefault();
        System.out.println(obj.foo());
        // ==> override foo on an OverridesDefault
        System.out.println(HasDefaultShim.MH_foo().invoke(obj));
        // ==> default foo on an OverridesDefault
        System.out.println(InvokeDefault.MH_foo().invoke(obj));
        // ==> default foo on an OverridesDefault
    }
    static MethodHandle MH_foo() {
        try {
            Class<?> it = HasDefault.class;
            MethodHandle mh = MethodHandles.lookup().findSpecial(it, "foo", 
methodType(String.class), it);
            return mh;
        } catch (ReflectiveOperationException ex) {
            throw new AssertionError(ex);
        }
    }
}
interface HasDefaultShim extends HasDefault {
    static MethodHandle MH_foo() {
        try {
            Class<?> it = HasDefault.class;
            Class<?> me = HasDefaultShim.class;
            MethodHandle mh = MethodHandles.lookup().findSpecial(me, "foo", 
methodType(String.class), me);
            assert(mh.type().parameterType(0) == me);
            // force the MH to accept all implementations of the interface
            mh = explicitCastArguments(mh, methodType(String.class, it));
            assert(mh.type().parameterType(0) == it);
            return mh;
        } catch (ReflectiveOperationException ex) {
            throw new AssertionError(ex);
        }
    }
}

Reply via email to