Resolution of the type of the returned method using its argument types

Suppose I have a method:

public class AwesomeClass {

    public <E> List<E> convertIterableToList(Iterable<E> iterable) {
        ...
    }

}

At runtime, how can I resolve the type of the return method based on the type of the argument? For example, I want to implement a hypothetical method resolveReturnTypewhose behavior is demonstrated in this small (pseudo-Java) unit test:

Method method = AwesomeClass.class.getDeclaredMethod("convertIterableToList", Iterable.class);

Type argumentType = {{{Set<String>}}}; // Just pretend this syntax works. :)
Type expectedReturnType = {{{List<String>}}};
Type actualReturnType = resolveReturnType(method, argumentType);

assertEquals(expectedReturnType, actualReturnType);

So far, I have tried to use the Guava TypeToken class , but I have not achieved much success.

+4
source share
2 answers

, , Type . @JVR, , ( ) TypeToken , .

static Type resolveReturnType(Type classType, Method method, Type... argTypes) {
  // this should resolve any class-level type variables
  Type returnType = TypeToken.of(classType)
      .resolveType(method.getGenericReturnType()).getType();
  Type[] parameterTypes = method.getGenericParameterTypes();

  TypeResolver resolver = new TypeResolver();
  for (int i = 0; i < parameterTypes.length; i++) {
    @SuppressWarnings("unchecked") // necessary for getSupertype call to compile
    TypeToken<Object> paramType =
        (TypeToken<Object>) TypeToken.of(parameterTypes[i]);
    @SuppressWarnings("unchecked") // necessary for getSupertype call to compile
    TypeToken<Object> argType =
        (TypeToken<Object>) TypeToken.of(argTypes[i]);

    if (method.isVarArgs() && i == parameterTypes.length - 1) {
      // TODO
    } else {
      TypeToken<?> argTypeAsParamType =
          argType.getSupertype(paramType.getRawType());
      resolver = resolver.where(
          paramType.getType(), argTypeAsParamType.getType());
    }
  }

  return resolver.resolveType(returnType);
}

: , E foo(E[] array), String[]. - , , , . , . , , ( ) :

public class Foo<T> {

  public <E> Map<T, E> convertIterableToMap(Iterable<E> iterable) {
    return null;
  }

  public static void main(String[] args) throws Exception {
    Method method = Foo.class.getMethod("convertIterableToMap", Iterable.class);

    Type instanceType = new TypeToken<Foo<Integer>>() {}.getType();
    Type setOfString = new TypeToken<Set<String>>() {}.getType();

    // prints: java.util.Map<java.lang.Integer, java.lang.String>
    System.out.println(resolveReturnType(instanceType, method, setOfString));
  }
}
+2

: .

:

<E> List<E> convertIterableToList(Iterable<E> iterable) E, . , iterable (1) , , , E .

, E .

(1) - class StringList implements List<String>, .

+1

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


All Articles