0

I have this Groovy snippet in my Spring application

 Class.forName(com.example.Name).getDeclaredMethods().each { method ->
                if (method.getName() == ('findId')) {
                    println method.returnType.name
                    println method.getName()
                }
            }

and interface:

public interface Find<E, D> {
    E findId(D id);
}

and class:

class Name implements Find<MyType,String>{
...
}

When my code snipet is executed I expect to have only one method with returned type MyType but I have 2?

class com.example.MyType with method findId

and

class java.lang.Object with method findId

From where this findBy can come from? From the interface or from Spring? (I do not have define method findID with returnedType Object (I am sure).

And Doc of getDeclaredMethods()

Returns an array of {@code Method} objects reflecting all the * methods declared by the class or interface represented by this * {@code Class} object. This includes public, protected, default * (package) access, and private methods, but excludes inherited methods. * The elements in the array returned are not sorted and are not in any * particular order. This method returns an array of length 0 if the class * or interface declares no methods, or if this {@code Class} object * represents a primitive type, an array class, or void. The class * initialization method {@code } is not included in the * returned array. If the class declares multiple public member methods * with the same parameter types, they are all included in the returned * array.

Xelian
  • 16,680
  • 25
  • 99
  • 152

1 Answers1

2

That's because of E generic type, and type erasure. Generic type is replaced with Object in byte code.

If you take a look at this example, you'll see that

private X first; 
private Y second; 
public X getFirst() { return first; } 
public Y getSecond() { return second; } 

turns to this after type erasure

private Object first; 
private Object second; 
public Object getFirst() { return first; } 
public Object getSecond() { return second; } 

The reason you see an additional method next to yours is because compiler adds a synthetic bridge method.

Quote related to the above example:

The NumericValue class implements the non-generic Comparable interface after type erasure, and the compiler adds a so-called bridge method . The bridge method is needed so that class NumericValue remains a class that implements the Comparable interface after type erasure.

See also:

Community
  • 1
  • 1
Predrag Maric
  • 23,938
  • 5
  • 52
  • 68
  • Ok but why such with class com.example.MyType is returned not only with Object? – Xelian May 21 '15 at 14:11
  • predrag-maric is on the right track here. Type erasure is what's going on. Specifically, the Java compiler is generating [bridge methods](https://docs.oracle.com/javase/tutorial/java/generics/bridgeMethods.html). – Keegan May 21 '15 at 14:26
  • @Xelian I've updated my answer. As Keegan already said, bridge methods are the answer. – Predrag Maric May 21 '15 at 14:28
  • So is there solution to change getDeclaredMethods with other method from Reflection API to get all methods? – Xelian May 21 '15 at 14:38
  • 1
    @Xelian You can call `isBridge()` on the method to check if it is a bridge method. – Predrag Maric May 21 '15 at 14:43
  • If isBridge() returns true-> this method's return type is Object. Thanks that works. – Xelian May 21 '15 at 15:30