java - 我想打印 hi GrandFather;但它似乎打印 hi Father

标签 java java-8 jvm invoke methodhandle

我要打印 hi GrandFather
但它似乎印喜父亲。而且我不明白如何区分 findSpecial 之间的使用和 findVirtual
我希望有人可以帮助我。谢谢

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();
}

console screenshot showing "hi Father" printed

最佳答案

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

您需要指定 Father.class作为上下文类,如 Father允许执行 super调用 GrandFather .如果您在不做进一步更改的情况下执行此操作,您会得到像 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);

这行得通,因为 SonFather是同一顶级类的内部类,因此允许访问彼此的私有(private)成员。如果它们不是同一顶级类中的类,in(…)将更改上下文类但清除私有(private)访问权限。在这种情况下,只有 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);

这适用于 FatherSon在同一个模块或Father的模块已打开Father的包裹到Son的反射模块。

关于java - 我想打印 hi GrandFather;但它似乎打印 hi Father,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60322808/

相关文章:

java - 重新部署时是否仍然无法摆脱 PermgenSpace 异常?

java - 删除未使用的字段是否会导致垃圾回收?

jakarta-ee - 帮我稳定这个 jRun 配置 (CF9/Win2k3/IIS6)

java - 似乎无法访问我的数组值,即使它正在工作

java-8 - 无法向 JBoss EAP 7.2 中嵌入的远程 ActiveMQ Artemis 发送消息

java - 在 JNI 客户端应用程序中设置较小的 JVM 堆大小

java - map 上复杂操作的问题

java - Maven : Deploy Local Project to Remote Server with dependencies

java - 如何将x个整数拆分为y个数组?

java - Android Studio 构建 gradle OutOfMemoryError