在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
。无论如何,我的问题是这样的:是否有简单的方法来获取一个类的方法的最专业版本的列表,而无需手动检查被覆盖的方法并将其过滤掉?
答案 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
}