You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何调用父类被重写的方法?toString()重写调用疑问

如何在子类重写toString后调用父类的实现?

这个问题我太熟悉了,Java的动态绑定机制在这里很容易让人困惑,先帮你梳理清楚整个场景和解决方案~

首先先还原你给出的类定义和JShell测试结果:

你的类代码

class Point { 
    int x; 
    int y; 
    Point(int x, int y) { this.x = x; this.y = y; } 
    public String toString() { return String.format("(%d,%d)",x,y); } 
}

class Line extends Point { 
    int l; 
    Line(int x, int y, int l) { super(x,y); this.l = l; } 
    public String toString() { return String.format("Length is %d", this.l); } 
}

JShell测试中的关键现象

你发现即使把Line对象强转成Point类型调用toString(),返回的依然是Line类的实现:

((Point) l).toString() ==> "Length is 3"

这是因为Java的实例方法调用是动态绑定的——运行时会根据对象的实际类型(而不是引用的声明类型)来决定调用哪个方法。所以不管你用Point还是Line的引用指向这个对象,只要实际对象是Line,就会调用Line重写后的toString()。

解决方案:调用父类Point的toString()方法

想要绕开动态绑定调用Point的toString(),有两种常用方式:

方式1:在子类Line中添加专门的方法(推荐)

直接在Line类里新增一个方法,通过super关键字调用父类的toString():

class Line extends Point { 
    // 已有的属性、构造方法、toString()...
    public String getPointToString() {
        return super.toString(); // 直接调用父类的toString实现
    }
}

之后调用时,只要把引用转成Line类型调用这个方法即可:

Point p = new Line(0,1,3);
System.out.println(((Line)p).getPointToString()); // 输出:(0,1)

方式2:使用反射(不推荐,仅当无法修改Line类时使用)

如果没办法修改Line的代码,可以用反射直接调用Point类的toString()方法,绕开动态绑定机制:

import java.lang.reflect.Method;

public class Test {
    public static void main(String[] args) throws Exception {
        Point p = new Line(0,1,3);
        // 获取Point类的toString方法
        Method pointToStringMethod = Point.class.getDeclaredMethod("toString");
        // 调用该方法,传入对象实例
        String result = (String) pointToStringMethod.invoke(p);
        System.out.println(result); // 输出:(0,1)
    }
}

反射的缺点是代码可读性差,而且会带来额外的性能开销,所以优先用第一种方式。

内容的提问来源于stack exchange,提问作者Rayshaun Thompson

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.07 12:12:50