问题描述
我要打印hi GrandFather
但是,它看起来像是在打招呼的父亲.而且我不明白如何区分findSpecial
和findVirtual
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
作为上下文类,因为允许Father
对GrandFather
执行super
调用.如果您不做进一步更改就执行此操作,则会出现类似java.lang.IllegalAccessException: no private access for invokespecial…
的异常.您必须更改lookup()
对象的上下文,才能访问Father
的private
功能:
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);
这是可行的,因为Son
和Father
是同一顶级类的内部类,因此允许访问彼此的私有成员.如果它们不是同一顶级类中的类,则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);
当Father
和Son
在同一个模块中,或者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.
这篇关于我想打个招呼的祖父;但似乎打个招呼的父亲的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!