题目比较绕。以下用一个简单的例子说明:
执行之后效果如下:
代码中,A的toString方法重写(override)了Object类的原始方法。
现在希望能够有方案对A对象调用Object类的toString方法从而获得A的索引值(reference)。
尝试一,反射,失败。
尝试二,研究super关键字的用法,发现没有类似于[b]a.[color=indigo]super[/color].toString()[/b]这样的写法,失败。
从而得出基本结论,采用编写代码的方式很难达到效果。
不过以下方法绕过了代码的语法规则和编译器的检查。可以达到要求的效果:
[list=1]
[*]把编写好的Java代码通过编译器生成类文件。
[*]使用Java ByteCode Editor打开生成的类文件。
[*]找到 invokevirtual A/toString()Ljava/lang/String;
[*]修改为 invokespecial java/lang/Object/toString()Ljava/lang/String;
[*]保存,执行,检查效果。
[/list]
invokespecial这个OpCode只有在以下三种情况下才能写出来:
[list=1]
[*]生成某个类的实例对象。
[*]在类的内部调用超类方法。
[*]在类的内部调用私有方法。
[/list]
因此如果不是手动修改ByteCode,似乎没什么办法实现以上的需求。
public class A
{
@Override
public String toString()
{
return "A";
}
public static void main(String[] args)
{
A a = new A();
B b = new B();
System.out.println(a.toString());
System.out.println(b.toString());
}
}
class B
{
}
执行之后效果如下:
A
B@c17164
代码中,A的toString方法重写(override)了Object类的原始方法。
现在希望能够有方案对A对象调用Object类的toString方法从而获得A的索引值(reference)。
尝试一,反射,失败。
import java.lang.reflect.Method;
public class A
{
public String toString()
{
return "A";
}
public static void main(String[] args) throws Exception
{
A a = new A();
Method m = Object.class.getMethod("toString");
System.out.println(m.invoke(a));
}
}
尝试二,研究super关键字的用法,发现没有类似于[b]a.[color=indigo]super[/color].toString()[/b]这样的写法,失败。
从而得出基本结论,采用编写代码的方式很难达到效果。
不过以下方法绕过了代码的语法规则和编译器的检查。可以达到要求的效果:
[list=1]
[*]把编写好的Java代码通过编译器生成类文件。
[*]使用Java ByteCode Editor打开生成的类文件。
[*]找到 invokevirtual A/toString()Ljava/lang/String;
[*]修改为 invokespecial java/lang/Object/toString()Ljava/lang/String;
[*]保存,执行,检查效果。
[/list]
A@11b86e7
invokespecial这个OpCode只有在以下三种情况下才能写出来:
[list=1]
[*]生成某个类的实例对象。
[*]在类的内部调用超类方法。
[*]在类的内部调用私有方法。
[/list]
因此如果不是手动修改ByteCode,似乎没什么办法实现以上的需求。