leangen / geantyref

Advanced generic type reflection library with support for working with AnnotatedTypes (for Java 8+)
Apache License 2.0
99 stars 15 forks source link

Add a way to resolve bounded types directly #15

Open leonard84 opened 2 years ago

leonard84 commented 2 years ago

Coming from https://github.com/coekie/gentyref/issues/5#issuecomment-968368485

I gave it a spin and came up with this:

  public static Type getResolvedReturnType(Method m, Type declaringType) {
    return resolveTypeVariableIfNecessary(GenericTypeReflector.getReturnType(m, declaringType));
  }

  public static Type getResolvedFieldType(Field f, Type declaringType) {
    return resolveTypeVariableIfNecessary(GenericTypeReflector.getFieldType(f, declaringType));
  }

  public static List<Type> getResolvedParameterTypes(Method m, Type declaringType) {
    return Arrays.stream(GenericTypeReflector.getParameterTypes(m, declaringType))
      .map(ReflectionUtil::resolveTypeVariableIfNecessary)
      .collect(Collectors.toList());
  }

  private static Type resolveTypeVariableIfNecessary(Type returnType) {
    if (returnType instanceof TypeVariable) {
      AnnotatedType annotatedType = GenericTypeReflector.annotate(returnType);
      return GenericTypeReflector.reduceBounded(annotatedType).getType();
    }
    return returnType;
  }

it seems to work, but I'm not sure its the best way. You can see the full change here https://github.com/leonard84/spock/tree/replace_gentyref_with_geantyref

I think that it might have value to have something like this in GenericTypeReflector directly, this way it could be optimized as well, the current implementation has to re-annotate the type that was discarded in GenericTypeReflector internally.

kaqqao commented 2 years ago

I'll look into adding an optional leaf transformation step during type resolution, that way an extra descent down the structure wouldn't be needed. But at the very least I'll add methods that avoid re-annotation. I'll notify you here when the next version is out.

Btw, you might want to always call reduceBounded in your current code, not only for variables, because I assume you'd also want wildcards and parameterized types reduced e.g. ? extends Number to Number or List<T extends Number to List<Number> etc.

leonard84 commented 2 years ago

I just wanted to avoid calling reduceBounded for the cases where it is already a simple type, e.g., String.

Do you have any performance measurements? Is it worth caching results or is it so cheap to calculate that it doesn't really matter?

On a related note, what would you suggest to resolve cases like this one below, where I have access to the parameter array of an invocation and would like to know the return type for that invocation? Of course the class param could be one of multiple parameters at different indexes and with different type variables.

<T> T create(Class<T> clazz)