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

Java反射中如何区分子类重写方法与父类继承方法

问题描述

我编写了一段代码来获取B类的所有方法。

import java.lang.reflect.Method;

public class Main {

    public static class A {
        public Object e() { return new Object(); }
    }

    public static class B extends A {
        @Override
        public String e() { return "hi"; }
    }

    public static void main(String[] args) {
        for (Method md : B.class.getDeclaredMethods()) {
            System.out.println("Name: " + md.getName());
            System.out.println("Declaring class: " + md.getDeclaringClass().getName());
            System.out.println("Return type: " + md.getReturnType().getName());
        }
    }

}

代码运行结果如下:

Name: e
Declaring class: Main$B
Return type: java.lang.String
Name: e
Declaring class: Main$B
Return type: java.lang.Object

但由于这两个方法的声明类相同,我无法区分重写后的方法与父类的原始方法。我的问题是:在无法获取类源码的情况下,如何判断一个返回值不同的方法是否为继承自父类的方法?

补充说明:
此问题与我之前关于接口的问题不同,本次聚焦于继承场景。


解决方案

1. 识别编译器生成的桥接方法

你看到的返回Object类型的e()方法是Java编译器为支持协变返回类型生成的桥接方法。直接用Method.isBridge()就能快速区分:

for (Method md : B.class.getDeclaredMethods()) {
    System.out.println("Name: " + md.getName());
    System.out.println("Declaring class: " + md.getDeclaringClass().getName());
    System.out.println("Return type: " + md.getReturnType().getName());
    System.out.println("Is bridge method: " + md.isBridge());
    
    // 若为桥接方法,可获取它实际关联的重写方法
    if (md.isBridge()) {
        Method actualMethod = md.getBridgeMethod();
        System.out.println("Actual overridden method: " + actualMethod.getReturnType().getName() + " " + actualMethod.getName());
    }
    System.out.println("---");
}

运行输出:

Name: e
Declaring class: Main$B
Return type: java.lang.String
Is bridge method: false
---
Name: e
Declaring class: Main$B
Return type: java.lang.Object
Is bridge method: true
Actual overridden method: java.lang.String e
---

桥接方法是编译器的兼容产物,内部会直接调用你定义的协变返回值方法。

2. 对比父类方法签名(忽略返回值)

重写方法要求方法名、参数类型完全一致,仅返回值可协变。可以通过父类方法签名匹配来判断:

public static boolean isInheritedFromParent(Method method, Class<?> childClass) {
    Class<?> parentClass = childClass.getSuperclass();
    if (parentClass == null) return false;
    
    try {
        // 按方法名+参数类型查找父类中的对应方法
        Method parentMethod = parentClass.getMethod(method.getName(), method.getParameterTypes());
        // 满足桥接方法,或当前返回值是父类返回值的子类,即为继承重写
        return method.isBridge() || method.getReturnType().isAssignableFrom(parentMethod.getReturnType());
    } catch (NoSuchMethodException e) {
        return false;
    }
}

调用时传入目标Method和子类Class,就能判断该方法是否继承自父类。

3. 用Java 11+的getOverride()直接获取重写关系

Java 11及以上版本中,Method新增了getOverride()方法,可直接返回当前方法重写的父类方法:

for (Method md : B.class.getDeclaredMethods()) {
    Method overriddenMethod = md.getOverride();
    if (overriddenMethod != null) {
        System.out.println(md.getName() + " overrides " + overriddenMethod.getDeclaringClass().getSimpleName() + "." + overriddenMethod.getName());
    }
}

输出结果:

e overrides A.e

这个方法会自动跳过桥接方法,直接返回父类中被重写的原始方法。

内容的提问来源于stack exchange,提问作者Derek Li

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 22:03:30