Java Class.getMethods() behavior on overridden methods

While writing a simple JSON serialiser using reflection in Java I was caught off guard by the behavior of Class.getMethods(). It appears that Java Class.getMethods() returns both overriding and overridden methods if the return type of the overriding method extends that of the overridden method.
So for example given the interfaces:

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

A.class.getMethods() returns and array of two methods as expected however B.class.getMethods() returns an array of 3 methods (which to me was a little counter intuitive). Of the 3, 1 corresponds to the y() as expected but the remaining two correspond to the original x() with return type A and the overriding version of x() with return type B respectively. This struck me as a little odd to have but the original x() in the array since its not accessible from anywhere. Anyway my question is this:
Is there and easy way to get a list of only the most specialised versions of a class’s methods without resorting to manually checking for overridden methods and filtering them out?

Answer

My understanding is that if you filter out methods for which isBridge() returns true, the unwanted method should go away.

It is an artefact of how Java implements covariant return types (bridge methods are also used for generics, but that doesn’t appear relevant to your use case).

edit Interestingly enough, while this works for classes, it doesn’t seem to work for interfaces. All three methods of B are marked as non-bridge and non-synthetic. However, if I create a non-abstract class C implementing B, its A x() is marked as both bridge and synthetic.

Leave a Reply

Your email address will not be published. Required fields are marked *