mibutec
mibutec

Reputation: 2997

How to get Generic Return type of a method using Reflections

Is there a way get the return type of a generic method- return type?

public interface MyGeneric<T> {
  T doSomething();
}

public interface MyElement extends MyGeneric<Element> {

}

public class Main {
  public static final void main(String[] args) {
    System.out.println(MyElement.class.getMethod("doSomething", new Class<?>[0]).magic()); // => Element
  }
}

Using Method.getReturnType() I get java.lang.Object without. Does the method "magic" exist?

Upvotes: 7

Views: 18144

Answers (2)

Mike Strobel
Mike Strobel

Reputation: 25623

Unfortunately, the reflection capabilities in the core Java library are rather poor for analyzing generic types. You can use the getGeneric... methods (e.g., getGenericReturnType()), but they don't work all that well, and they usually return Type instances instead of Class instances. I find this very clumsy to work with.

I have written my own reflection API, based the .NET's, which I feel is more consistent (particularly where generics are concerned). Consider the following output:

import com.strobel.reflection.Type;

interface MyGeneric<T> {
    T doSomething();
}

interface Element {}

interface MyElement extends MyGeneric<Element> {}

class Main {
    public static final void main(String[] args) throws NoSuchMethodException {
        // prints "class java.lang.Object":
        System.out.println(
            MyElement.class.getMethod("doSomething").getReturnType()
        );
        // prints "T":
        System.out.println(
            MyElement.class.getMethod("doSomething").getGenericReturnType()
        );
        // prints "Element":
        System.out.println(
            Type.of(MyElement.class).getMethod("doSomething").getReturnType()
        );
    }
}

You're welcome to use my library. I actually just committed a bug fix that prevented this example from working (it's in the tip of the develop branch).

Upvotes: 8

V G
V G

Reputation: 19002

No, that magic does not exist generally. If you want to make a trick in order to get to that data, you can require that data in your interface like explained here.

On the other side, if your type is special (like a List), you can do that. See this answer for special types.

Upvotes: 1

Related Questions