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
相关产品推荐
相关产品推荐

