【问题标题】:java method return type is not actual typejava方法返回类型不是实际类型
【发布时间】:2018-11-19 02:35:57
【问题描述】:

java 方法返回类型不是实际类型。例如,

public interface Foo<X extends TypeA> {
    public X hello();
}

public class Bar implements Foo<TypeB> {
    @Override
    public TypeB hello() {
       ...
    }
}

Method method = Bar.class.getDeclaredMethod("hello");
Class returnType = method.getReturnType();

returnType 是 TypeA,而不是 TypeBTypeBTypeA 的子类。

如何获取方法的实际返回类型?它是TypeB,而不是TypeA

更新

我用过

Method[] methods = Bar.class.getDeclaredMethods();

然后遍历这些方法。该方法返回超类。验证 getDeclaredMethod("hello") 确实返回子类类型。为什么它们不同?

【问题讨论】:

  • X 被 TypeA 绑定。在这种情况下如何使用反射?谢谢。
  • 我使用 JDK 11-ea+17 得到 TypeB。您使用的是什么版本的 Java?
  • java版本“1.8.0_60”
  • 我也用 JDK8 获得 TypeB。
  • 如果仍然发生,请提供mvce,因为问题中的代码甚至无法编译。

标签: java methods reflection return-type


【解决方案1】:

如果您使用getDeclaredMethods() 遍历所有声明的方法,您会发现两个签名相似的方法:

  • TypeB hello()(这是你所期望的)
  • TypeA hello()(你说的就是这个)

查看字节码会发现以下条目:

public hello()Ltest/TypeB;

//... the bytecode for your method

public synthetic bridge hello()Ltest/TypeA;

//... bytecode that delegates to hello()Ltest/TypeB

这是 javac 编译器的效果,它引入了合成桥接方法 TypeA hello(),它只委托给 TypeB hello()

原因是只能虚拟调用相同签名的方法。由于接口签名是TypeA hello(),因此对接口的任何调用都会在实现中调用TypeA hello()。然而您的课程Bar 不包含此方法,而是替换TypeB hello()。为了解决这个问题,javac 选择了桥接方法(将其委托给替换)。我认为这将在运行时为他们节省大量工作。

因此,您的问题不是来自返回错误类型的方法,而是您的代码返回了错误的方法。如果您迭代方法,请在它们上调用isSynthetic()(true 表示它不是感兴趣的方法)。

【讨论】:

  • 最后一句没看懂。我可以从调试中看到重复的方法。如何忽略接口中定义的方法,保留类声明的方法?谢谢。
  • 错误的方法是synthetic。您可以在 Method 对象上调用 isSynthetic()。每个返回 true 的方法都不是在源代码中实现的方法。
猜你喜欢
  • 2021-03-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-06-07
  • 2012-10-18
  • 1970-01-01
  • 1970-01-01
  • 2021-06-28
相关资源
最近更新 更多