我想打印 hi GrandFather;但它似乎打印 hifather

Chr*_*nos 5 java jvm invoke java-8 methodhandle

我要打印 hi GrandFather

但它似乎打印喜父亲。我不明白如何区分findSpecialfindVirtual

我想要有人可以帮助我。谢谢

class GrandFather{
    void thinking(){
        System.out.println("hi GrandFather");

    }
}
class Father extends GrandFather{
    void thinking(){
        System.out.println("hi Father");
    }
}
class Son extends Father{
    void thinking(){
            MethodType mt=MethodType.methodType(void.class);

            //MethodHandle mh=MethodHandles.lookup().findVirtual(GrandFather.class,"thinking",mt).bindTo(this);
            MethodHandle mh;
                mh = MethodHandles.lookup().findSpecial(GrandFather.class,"thinking",mt,getClass());
                mh.invoke(this);
    }
}
public static void main(String[] args){
    (new MethodHandleTest().new Son()).thinking();
}
Run Code Online (Sandbox Code Playgroud)

控制台屏幕截图显示打印了“嗨父亲”

Hol*_*ger 6

的最后一个参数findSpecial指定调用的上下文类。您指定了getClass(),这将导致Son.class。一个super从调用Son只能在结束了Father,就像一个普通的super.thinking()源代码中调用。

您需要指定Father.class为上下文类,因为Father允许执行superGrandFather. 如果您在没有进一步更改的情况下执行此操作,则会得到类似java.lang.IllegalAccessException: no private access for invokespecial…. 您必须更改lookup()对象的上下文,才能访问以下private功能Father

MethodType mt = MethodType.methodType(void.class);
MethodHandle mh = MethodHandles.lookup().in(Father.class)
    .findSpecial(GrandFather.class, "thinking", mt, Father.class);
mh.invoke(this);
Run Code Online (Sandbox Code Playgroud)

这是有效的,因为SonFather是同一顶级类的内部类,因此允许访问彼此的私有成员。如果它们不是同一顶级类中的类,in(…)将更改上下文类但清除私有访问权限。在这种情况下,只有 Java 9 及更新版本有官方解决方案:

MethodType mt = MethodType.methodType(void.class);
MethodHandle mh = MethodHandles.privateLookupIn(Father.class, MethodHandles.lookup())
    .findSpecial(GrandFather.class, "thinking", mt, Father.class);
mh.invoke(this);
Run Code Online (Sandbox Code Playgroud)

FatherSon在同一个模块中或Father的模块已打开Father的包到Son的模块进行反射时,此方法有效。

  • @Eugene,语义应该与“invokespecial”字节码指令相匹配,因此,当您想要调用接口的“default”方法时,接收器类型会有所不同。此外,您可以使用它来调用您自己的类中的“私有”方法。问题应该是相反的,当调用者类参数的唯一合理值是已经封装在“Lookup”对象中的查找类时,为什么我们需要最后一个参数。 (3认同)