Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 799
rtn Avatar asked Jun 01 '11 16:06

rtn


People also ask

Can I change the return type in an overridden method?

Yes. It is possible for overridden methods to have different return type .

How do we identify if a method is an overridden method?

Reflection can be used to determine if a method is overridden. The code is a little bit tricky. For instance, you need to be aware that you have a runtime class that is a subclass of the class that overrides the method. You are going to see the same runtime classes over and over again.

What happens when you override a method?

Instance Methods The ability of a subclass to override a method allows a class to inherit from a superclass whose behavior is "close enough" and then to modify behavior as needed. The overriding method has the same name, number and type of parameters, and return type as the method that it overrides.

Can you access overridden method in Java?

Instance methods can be overridden only if they are inherited by the subclass. A method declared final cannot be overridden. A method declared static cannot be overridden but can be re-declared. If a method cannot be inherited, then it cannot be overridden.


2 Answers

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.

like image 93
NPE Avatar answered Sep 28 '22 07:09

NPE


What you have is called "covariant return".

As aix points out, it seems you have to deal with bridge methods. Read this: http://stas-blogspot.blogspot.com/2010/03/java-bridge-methods-explained.html (ignore the text about generics) and this: Problem in the GetDeclaredMethods (java)

like image 29
ignis Avatar answered Sep 28 '22 06:09

ignis