【问题标题】:Determining if a method overrides another at runtime确定一个方法是否在运行时覆盖另一个方法
【发布时间】:2026-01-23 11:55:02
【问题描述】:

我想知道是否有任何方法可以确定给定java.lang.Method 对象表示的方法是否覆盖另一个java.lang.Method 对象表示的方法?

我正在处理Stronlgy typed javascript,我需要能够知道一个方法是否覆盖另一个方法,以便能够将它们重命名为更短的名称。

在这种情况下,我说的是覆盖的扩展定义,由 @Override 注释支持,其中包括接口和抽象类方法的实现。

我对任何涉及直接反射或使用任何已经这样做的库的解决方案都很满意。

【问题讨论】:

  • 这当然是可能的,但据我所知,没有内置的方法可以做到这一点。您所要做的就是检查JLS 中覆盖定义的条件。
  • 我知道,但这远非微不足道,尤其是当我们谈论泛型方法,或使用声明类的泛型类型参数的方法时。
  • 如果您在所有覆盖方法上使用 Override 注解,您只需检查注解是否存在。
  • @jeff Override 注释是一个 SOURCE 注释,这意味着它不存在于编译文件中。
  • @Override 注释具有retention=source,因此它不会出现在已编译的类中。最重要的是,我正在编写的程序应该分析第三方编写的代码,因此,我对类没有那种控制权。

标签: java inheritance reflection overriding


【解决方案1】:

您可以简单地交叉检查方法名称和签名。

public static boolean isOverriden(Method parent, Method toCheck) {
    if (parent.getDeclaringClass().isAssignableFrom(toCheck.getDeclaringClass())
            && parent.getName().equals(toCheck.getName())) {
         Class<?>[] params1 = parent.getParameterTypes();
         Class<?>[] params2 = toCheck.getParameterTypes();
         if (params1.length == params2.length) {
             for (int i = 0; i < params1.length; i++) {
                 if (!params1[i].equals(params2[i])) {
                     return false;
                 }
             }
             return true;
         }
    }
    return false;
}

但是,由于您的目标是重命名方法,因此您可能希望使用字节码分析/操作库,例如 ASM,您可以在其中执行相同的测试以及轻松修改方法的名称,如果方法返回真。

【讨论】:

  • 不要忘记return 类型、throws 声明或泛型兼容性。
  • @Jeffrey 返回类型被检查,throws 声明在这里无关紧要,因为如果方法的名称和签名与父类中的方法相同,则会覆盖该方法。出于同样的原因,泛型也无关紧要。
  • 返回类型真的很重要吗?我不认为他们这样做,他们不是方法签名的一部分。然后我不同意泛型无关紧要。如果你有class Parent&lt;T&gt;void foo(T param)class Child&lt;String&gt; extends Parent&lt;T&gt;void foo(String param)。您的实现不会无法识别最重要的关系吗?
  • 次要建议 - Array.equals() 可以在比较循环中节省一些输入。例如return Arrays.equals(params1, params2);
  • @Vulcan,根据JLS §8.4.2,返回类型不是方法签名的一部分