我要打印 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();
}
最佳答案
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);
这行得通,因为
Son
和 Father
是同一顶级类的内部类,因此允许访问彼此的私有(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);
这适用于
Father
和 Son
在同一个模块或Father
的模块已打开Father
的包裹到Son
的反射模块。
关于java - 我想打印 hi GrandFather;但它似乎打印 hi Father,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60322808/