`
regular
  • 浏览: 76958 次
  • 性别: 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
分享到:
评论

相关推荐

    java复习资料(学生版).doc

    * 在子类中使用关键字super可以调用被子类覆盖的父类中的方法。 异常处理 * 在Java语言中,通常把可能发生异常的代码放到try块中,并用紧跟其后的catch块来捕获和处理异常。 抽象类和接口 * 抽象方法是一种仅有...

    java习题集4java习题集4.doc

    5. final关键字:final修饰的类不能被继承,final修饰的方法不能被子类覆盖。final还可以修饰变量,使其成为常量。 6. 构造方法:子类在实例化时,其构造方法会调用父类的构造方法,这是通过super关键字实现的。 7...

    JAVA中的继承与抽象

    继承中的构造方法在子类的构造方法的第一行代码如果没有调用父类的构造或者没有调用子类的其他构造,则默认调用父类无参构造。super关键字的用法有三种:1. 在子类的成员方法中,访问父类的成员变量。2. 在子类的...

    java秋招笔试面试知识点总结

    内部类可以直接访问外部类的所有成员,包括私有成员,而外部类访问内部类的成员则需要创建内部类对象。内部类可以使用不同的访问修饰符,包括默认修饰符、public、private、protected等。 以上是对Java基础知识点的...

    《Java程序设计》复习题答案1.pdf

    4. **多态性与方法的重载、覆盖**:多态性允许一个接口有多种实现,方法重载是在同一类中定义多个同名但参数不同的方法,而方法覆盖发生在子类中,子类重写父类的方法。重载是编译时多态,覆盖是运行时多态。 5. **...

    第讲-Java类的特性优秀文档.ppt

    修饰方法时,方法不能被子类覆盖;修饰类时,类不能被继承。 `instanceof`运算符用来检查一个对象是否属于某个类或其子类,这对于多态场景下的类型判断非常有用。 总结来说,Java类的特性是面向对象编程的重要组成...

    小白都能学会的Java文档.pdf

    当final用于方法时,这个方法不能被子类覆盖。当final用于变量时,如果是基本数据类型,变量值不可更改;如果是引用类型,则引用本身不可更改,但引用所指向的对象内容可以修改。 super和this关键字在Java中用于...

    清华IT深入Java类高级优秀PPT.ppt

    `private`方法不能被子类重写,因为它们对外部类是不可见的。 5. **内部类的引用**: 内部类的对象包含对外部类对象的引用,可以通过`OuterClassName.this`引用外部类对象,而`InnerClassName.this`则表示内部类...

    java教学

    方法覆盖通常发生在子类需要扩展或修改父类功能时。子类中的覆盖方法必须与父类中被覆盖的方法有相同的名称、参数列表和访问修饰符。返回类型可以不同,但不推荐这样设计,因为这并不构成方法的重载。 7. **构造...

    JAVA学习笔记

    在处理对象时,打印对象通常会调用toString方法,该方法在Object类中定义,但可以被子类覆盖以返回对象的字符串表示。在Java中,比较对象相等性通常使用equals方法而不是==运算符,后者比较的是引用是否指向同一对象...

    java 程序设计笔记

    final 方法不能被子类覆盖,固定具体操作;final 域及 final 局部变量只能被赋值一次。 - abstract:抽象类抽取公共属性,需要继承,不能用 final 修饰;抽象方法为所有子类定义一个统一的接口,在子类中必须被实现...

    java关键字总结

    final修饰的参数对于基本类型的参数无太大意义,但对于引用类型参数来说,可以防止在方法内部被重新指向。 关键字static用于定义类级别成员,比如静态变量和静态方法。这些成员属于类本身,而不是类的实例。静态...

    final类,方法,变量

    这保证了在多态环境中调用该方法时,总是执行父类中的特定实现。例如,`Object`类的`equals()`和`hashCode()`方法被声明为`final`,以确保所有类都遵循统一的比较和哈希计算规则。 然后是`final`变量。`final`变量...

    黑马程序员python基础班教程笔记:(48)继承以及单继承的介绍.docx

    - 父类的公共属性和方法会被子类继承,私有属性和方法则不会。 - 子类可以添加自己的属性和方法,同时可以覆盖父类的方法。 - 尊重封装原则,避免直接访问或修改私有属性和方法,以维护代码的稳定性和安全性。 ...

    面向对象核心技术.pdf

    在方法或类中使用final,还可以防止方法被子类重写或类被继承。 在面向对象编程中,这三个核心特性——封装、继承和多态,以及控制符和final关键字等,共同构成了面向对象程序设计的基石,使得程序设计更加模块化、...

    十分钟JAVA从入门到放弃

    - 当一个类有很多子类,并且这些子类都重写了父类的某个方法时,子类对象的上转型对象在调用这个方法时就可能表现出不同的行为,这就是多态性。 #### 抽象abstract - **抽象类**:不能直接实例化,主要用于定义一...

    Java关键字总结

    - **方法锁定**:使用`final`修饰的方法不能被继承类覆盖或重新定义。这样做有两个目的:一是锁定方法的行为,防止子类改变其实现;二是确保继承结构中的方法行为一致,不会被覆盖。需要注意的是,类中的所有`...

Global site tag (gtag.js) - Google Analytics