本文介绍了我想打个招呼的祖父;但似乎打个招呼的父亲的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我要打印hi GrandFather

但是,它看起来像是在打招呼的父亲.而且我不明白如何区分findSpecialfindVirtual

But it seems to print hi father. And I am not understand how to diff the use between findSpecial and findVirtual

我希望有人可以帮助我.谢谢

I want someone can help me. Thank you

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

推荐答案

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

The last argument to findSpecial specifies the context class for the invocation. You specified getClass(), which will result in Son.class. A super invocation from Son can only end up in Father, just like an ordinary super.thinking() call in source code.

您需要指定Father.class作为上下文类,因为允许FatherGrandFather执行super调用.如果您不做进一步更改就执行此操作,则会出现类似java.lang.IllegalAccessException: no private access for invokespecial…的异常.您必须更改lookup()对象的上下文,才能访问Fatherprivate功能:

You need to specify Father.class as context class, as Father is allowed to perform a super invocation to GrandFather. If you do this without further changes, you’d get an exception like java.lang.IllegalAccessException: no private access for invokespecial…. You have to change the context of your lookup() object, to be able to access private features of 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是同一顶级类的内部类,因此允许访问彼此的私有成员.如果它们不是同一顶级类中的类,则in(…)将更改上下文类,但清除专用访问权限.在这种情况下,只有Java 9和更高版本具有官方解决方案:

This works, because Son and Father are inner classes of the same top level class, so accessing each other’s private members is allowed. If they were not classes within the same top level class, in(…) would change the context class but clear the private access permission. In that case, only Java 9 and newer have an official solution:

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的模块进行反射时,此功能有效.

This works when Father and Son are in the same module or Father’s module has opened Father’s package to Son’s module for Reflection.

这篇关于我想打个招呼的祖父;但似乎打个招呼的父亲的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-17 01:04