Java Class.getMethods () Behavior with Overridden Methods

When writing a simple JSON serializer using reflection in Java, I was taken aback by the behavior of the Class.getMethods () class. It seems that Java Class.getMethods () returns both overriding and overridden methods if the return type of the override method extends the override 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 an array of two methods, as expected however B.class.getMethods() returns an array of 3 methods (which was a bit contrasting intuitive for me). Out of 3, 1 corresponds to y() , as expected, but the other two correspond to the original x() with the return type A and the overriding version x() with the return type B respectively. It seemed a little strange to me, but the original x() in the array, since it is not accessible anywhere. Anyway, my question is this:
Is there an easy way to get a list of only the most specialized versions of class methods without resorting to manually checking overridden methods and filtering them?

+5
source share
3 answers

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

This is an artifact of how Java implements covariant return types (mod methods are also used for generics, but this is not like your use case).

edit Interestingly, although this works for classes, it does not work for interfaces. All three methods B are marked as non-bridge and non-synthetic. However, if I create a non-abstract class C that implements B , its A x() marked with both a bridge and a synthetic one.

+6
source

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 generics text) and this: The problem is in GetDeclaredMethods (java)

+3
source

One way to say: B.class.getDeclaredMethods() , however, this will only return methods declared in B. So, if you have C extends B that implements A, C.class.getDeclaredMethods() will not return methods that you have not redefined .

if you want iteration, a good way to do it

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

Source: https://habr.com/ru/post/925152/


All Articles