0

I have the following setup

class A {

    @Override
    public String toString(){
        return "A's toString";
    }

}

class B extends A {

    @Override
    public String toString(){
        return "B's toString";
    }

}

I have an instance of class B and I'd like to call B.super.toString ONLY using reflection. Note that class A and B are not specific, I am working with objects which can be other than A or B but the method I'm looking for is surely in the class. I have tried the followings without any success:

1:

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

In the case above the value will be "A's toString" which is what I expect, however this is not good for me as this requires an instantiation of the super class which is not always possible (e.g the super class is abstract) moreover the new instance' fields are not identical to the object's super class's field. Not a solution for me.

2:

...
private void callSuperToString(Object object){
    Method method = object.getClass().superClass().getDeclaredMethod("toString");
    String value = (String) method.invoke(object);
}

In this case value will be "B's toString" which is not as the expected "A's toString". Is it possible to achieve what I'm trying to do here?

EDIT:

3

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

The following throws this exception: java.lang.IllegalAccessException: no private access for invokespecial

EDIT 2:

Yes this might be a duplicate. I found the answer in the link provided which was not the accepted answer. The following works perfectly:

Solution:

...
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);
}
Community
  • 1
  • 1
Gabor Peto
  • 642
  • 11
  • 24
  • 2
    in class B your overridden method returns void??? – Sarthak Mittal Nov 27 '14 at 11:33
  • @Sarthak Mittal: Thanks for pointing out. It was just a typo. it returns a string. – Gabor Peto Nov 27 '14 at 11:41
  • The suggested answer in the other question throws the following exception: java.lang.IllegalAccessException: no private access for invokespecial. Deos anyone know the reason for that? Updated the question to include the 3rd test case. – Gabor Peto Nov 27 '14 at 11:45

0 Answers0