jeudi 3 décembre 2015

MethodHandle to a getter/setter from another class gvies a NoSuchFieldError

Suppose I have simple javabean MyPerson with a name getter and setter:

public class MyPerson {

    private String name;

    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }

}

Now I am running this main code that simply gets and sets that name field:

    public static void main(String[] args) throws Throwable {
        MethodHandles.Lookup lookup = MethodHandles.lookup();
        MethodHandle getterMethodHandle = lookup.findGetter(MyPerson.class, "name", String.class);
        MethodHandle setterMethodHandle = lookup.findSetter(MyPerson.class, "name", String.class);
        MyPerson a = new MyPerson();
        a.setName("Batman");
        System.out.println("Name from getterMethodHandle: " + getterMethodHandle.invoke(a));
        setterMethodHandle.invoke(a, "Robin");
        System.out.println("Name after setterMethodHandle: " + a.getName());
    }

If I add that main() method on the class MyPerson, I get what I expect:

Name from getterMethodHandle: Batman
Name after setterMethodHandle: Robin

If I add that same main() method on another class in another package, I get this weird error:

Exception in thread "main" java.lang.NoSuchFieldException: no such field: http://ift.tt/1Q2MiYW
    at java.lang.invoke.MemberName.makeAccessException(MemberName.java:875)
    at java.lang.invoke.MemberName$Factory.resolveOrFail(MemberName.java:990)
    at java.lang.invoke.MethodHandles$Lookup.resolveOrFail(MethodHandles.java:1373)
    at java.lang.invoke.MethodHandles$Lookup.findGetter(MethodHandles.java:1022)
    at batman.other.MyMain.main(MyMain.java:28)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)
Caused by: java.lang.NoSuchFieldError: name
    at java.lang.invoke.MethodHandleNatives.resolve(Native Method)
    at java.lang.invoke.MemberName$Factory.resolve(MemberName.java:962)
    at java.lang.invoke.MemberName$Factory.resolveOrFail(MemberName.java:987)

Why? MyPerson's getter/setters are public, so there's no reason why MyMain shouldn't be to use them, even through MethodHandles.

Using JDK 8 with source/target level java 8.





Aucun commentaire:

Enregistrer un commentaire