重写方法上的Java Class.getMethods()行为

时间:2011-06-01 16:14:08

标签: java reflection

在Java中使用反射编写一个简单的JSON序列化程序时,我对Class.getMethods()的行为感到措手不及。如果重写方法的返回类型扩展了重写方法的返回类型,则Java Class.getMethods()似乎返回重写和重写方法。
例如,给定接口:

static interface A {
  A x();
  A y();
}
static interface B extends A {
  B x();
  A y();
}

A.class.getMethods()按预期返回两个方法的数组 但是B.class.getMethods()返回一个包含3个方法的数组(对我来说这有点反直觉)。 在3中,1对应于预期的y(),但其余两个对应于返回类型为x()的原始A和返回类型为x()的覆盖版本{分别为{1}}。这让我觉得有点奇怪,因为它不能从任何地方访问数组中的原始B。无论如何,我的问题是这样的:是否有简单的方法来获取一个类的方法的最专业版本的列表,而无需手动检查被覆盖的方法并将其过滤掉?

3 个答案:

答案 0 :(得分:7)

我的理解是,如果您过滤掉isBridge()返回true的方法,那么不需要的方法就会消失。

这是Java如何实现协变返回类型的假象(桥接方法也用于泛型,但这似乎与您的用例无关)。

编辑有趣的是,虽然这适用于类,但它似乎不适用于接口。 B的所有三种方法都标记为非桥和非合成。但是,如果我创建一个实现C的非抽象类B,则其A x()将被标记为桥接和合成。

答案 1 :(得分:4)

你所拥有的是“协变回归”。

正如aix指出的那样,你似乎必须处理桥接方法。 读这个: http://stas-blogspot.blogspot.com/2010/03/java-bridge-methods-explained.html(忽略有关泛型的文字) 还有这个: Problem in the GetDeclaredMethods (java)

答案 2 :(得分:0)

一种方法是说:B.class.getDeclaredMethods(),但是,这只会返回B中分解的方法。所以,如果你有C扩展B实现A,C.class.getDeclaredMethods()不会返回你避开的方法被覆盖了。

如果你想迭代,那么这样做的好方法是

for (Method m: B.class.getMethods()) {
  if (m.getDeclaringClass() == Object.class || m.declaringClass() == A.class) 
    continue;
  // otherwise do some stuff
}