【问题标题】:How do you find a parameterised overridden method with reflection?您如何找到带有反射的参数化覆盖方法?
【发布时间】:2019-12-08 17:35:27
【问题描述】:

假设如下情况:

interface A<T>{
    default void foo(T t){
        System.err.println(new Exception().getStackTrace()[0] + " " + t);
    }
}

interface B<T extends SomeConcreteType> extends A<T>{
    @Override
    default void foo(T t){
        System.err.println(new Exception().getStackTrace()[0] + " " + t);
    }
}

我正在尝试使用反射从 B 的 foo 方法转到 A 的 foo 方法。 鉴于两种方法的后擦除参数类型不同,我该怎么做呢?

【问题讨论】:

  • 我认为这通常是不可能的。
  • 试过class.getMethod("foo").getDeclaringClass();?来自here
  • 我不确定“两种方法的后擦除参数类型不同”。实际上(并跳过“后擦除”,这实际上没有意义),这些方法具有相同的参数类型。
  • 不知道你想做什么以及为什么你认为你需要反思。 super.foo(t) 怎么了?
  • 当你试图通过反射访问一个方法时,不管你在哪里做,表单总是一样的,即A.class.getDeclaredMethod("foo", Object.class),不管你在B.foo里面或Hello.main。所以B.foo的擦除参数类型完全不相关。

标签: java generics reflection


【解决方案1】:

在这种情况下,Java 编译器将生成 2 个方法,因此您可以同时使用它们,其中一个将具有与 A.class:foo(Object) 相同的签名,因为它是覆盖工作所必需的,第二个将有基本的泛型类型foo(SomeConcreteType),第一个方法只是调用第二个方法,所以编译后你的A和B类基本上是这样的:

interface A<T>{
    default void foo(Object t){
        System.err.println(new Exception().getStackTrace()[0] + " " + t);
    }
}

interface B<T extends SomeConcreteType> extends A<T>{
    @Override
    default void foo(Object t){ 
        this.foo((SomeConcreteType) t);
    }

    default void foo(SomeConcreteType t){
        System.err.println(new Exception().getStackTrace()[0] + " " + t);
    }
}

(跳过通用元数据)

所以你可以使用A/B.class.getDecalredMethod("foo", Object.class)B.class.getDecalredMethod("foo", SomeConcreteType.class)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-03-08
    • 2012-03-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-23
    相关资源
    最近更新 更多