`
regular
  • 浏览: 76020 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

如何在类外部调用被子类覆盖的父类方法

    博客分类:
  • Java
阅读更多
题目比较绕。以下用一个简单的例子说明:
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关键字的用法,发现没有类似于a.super.toString()这样的写法,失败。

从而得出基本结论,采用编写代码的方式很难达到效果。

不过以下方法绕过了代码的语法规则和编译器的检查。可以达到要求的效果:
  1. 把编写好的Java代码通过编译器生成类文件。
  2. 使用Java ByteCode Editor打开生成的类文件。
  3. 找到 invokevirtual A/toString()Ljava/lang/String;
  4. 修改为 invokespecial java/lang/Object/toString()Ljava/lang/String;
  5. 保存,执行,检查效果。

A@11b86e7

invokespecial这个OpCode只有在以下三种情况下才能写出来:
  1. 生成某个类的实例对象。
  2. 在类的内部调用超类方法。
  3. 在类的内部调用私有方法。


因此如果不是手动修改ByteCode,似乎没什么办法实现以上的需求。
0
3
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics