我有以下设置
class A {
@Override
public String toString(){
return "A's toString";
}
}
class B extends A {
@Override
public String toString(){
return "B's toString";
}
}
我有一个B类的实例,我想只使用反射调用B.super.toString。请注意,A类和B类不是特定的,我正在使用除A或B以外的对象,但我正在寻找的方法肯定在课堂上。我尝试了以下但没有取得任何成功:
...
private void callSuperToString(Object object){
//class B is an example for object.getClass in this example
String value = (String) object.getClass()
.getSuperclass()
.getMethod("toString")
.invoke(object.getClass().getSuperclass().newInstance());
}
在上面的情况下,值将是“A的toString”,这是我所期望的,但这对我不利,因为这需要超类的实例化,这并不总是可能的(例如,超类是抽象的)此外,新实例'字段与对象的超类字段不同。对我来说不是解决方案。
...
private void callSuperToString(Object object){
Method method = object.getClass().superClass().getDeclaredMethod("toString");
String value = (String) method.invoke(object);
}
在这种情况下,值将是“B的toString”,它不是预期的“A的toString”。是否有可能实现我在这里要做的事情?
编辑:
...
private void callSuperToString(Object object){
MethodHandle handle = MethodHandles.lookup()
.findSpecial(object.getClass().getSuperclass(), "toString",
MethodType.methodType(String.class),
object.getClass());
value= (String) handle.invoke(object);
}
以下引发此异常:java.lang.IllegalAccessException:invokespecial没有私有访问权限
编辑2:
是的,这可能是重复的。我在提供的链接中找到了答案,这不是公认的答案。以下工作完美:
...
private void callSuperToString(Object object){
Field IMPL_LOOKUP = MethodHandles.Lookup.class.getDeclaredField("IMPL_LOOKUP");
IMPL_LOOKUP.setAccessible(true);
MethodHandles.Lookup lkp = (MethodHandles.Lookup) IMPL_LOOKUP.get(null);
MethodHandle h1 = lkp.findSpecial(object.getClass().getSuperclass(), "toString",
MethodType.methodType(String.class),
object.getClass());
value= (String) h1.invoke(object);
}