使用反射确定方法是否覆盖另一个方法?

10

这是否可能?

我找到的唯一解决方案通常认为如果Class B可以从Class A分配,并且如果Method AMethod B具有相同的签名,则将方法视为被覆盖。但它并不能涵盖所有情况!

例如,我想处理这种情况:

interface Foo<T> {
    void doStuff(T arg);    
}

class FooImpl implements Foo<String> {
    public void doStuff(String args) {
        //Is overriden!  
    }
}

我还想检查一下方法B是否对方法A可见(包括作用域等)。

您有没有经验可以确定某个方法是否被覆盖?

谢谢


1
不要忘记 @Overridable 可选注解。 - Joop Eggen
1个回答

5

如果没有泛型参与,有一种现有的答案可以确定方法是否被覆盖。

由于类型擦除的缘故,Java会完全去除泛型类型。因此,字节码将如下所示:

class FooImpl implements Foo<java.lang.String> {
  FooImpl();
    Code:
       0: aload_0
       1: invokespecial #10                 // Method java/lang/Object."<init>":()V
       4: return

  public void doStuff(java.lang.String);
    Code:
       0: return

  public void doStuff(java.lang.Object);
    Code:
       0: aload_0
       1: aload_1
       2: checkcast     #21                 // class java/lang/String
       5: invokevirtual #23                 // Method doStuff:(Ljava/lang/String;)V
       8: return
}

这里有两个doStuff方法。这是一个桥接方法。它只是进行类型转换并调用void doStuff(java.lang.String),因此实际上void doStuff(java.lang.String)没有被覆盖,但是void doStuff(java.lang.Object)被覆盖了。当你使用多态性时:

Foo foo = new FooImpl();
foo.doStuff("ABC")

实际上它调用的是void doStuff(java.lang.Object)。因此,如果您使用上面的链接来检测是否覆盖了void doStuff(java.lang.Object),它将报告是。

public static void main(java.lang.String[]);
    Code:
       0: new           #1                  // class FooImpl
       3: dup
       4: invokespecial #22                 // Method "<init>":()V
       7: astore_1
       8: aload_1
       9: ldc           #23                 // String ABC
      11: invokeinterface #25,  2           // InterfaceMethod Foo.doStuff:(Ljava/lang/Object;)V
      16: return

非常有帮助,感谢您的澄清!由于我没有找到任何能够完成这项任务的库,我将自己实现它。如果最终得出一个简洁而优雅的解决方案,我会在这里发布它。 - Simon V.
我刚刚在这里发布了我的解决方案(使用 Kotlin 编写):https://dev59.com/Sm445IYBdhLWcg3wgqrT - Simon V.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接