Java 解析方法';s使用其参数类型返回类型

Java 解析方法';s使用其参数类型返回类型,java,generics,reflection,guava,Java,Generics,Reflection,Guava,假设我有一个方法: public class AwesomeClass { public <E> List<E> convertIterableToList(Iterable<E> iterable) { ... } } 到目前为止,我一直在尝试使用番石榴的课程,但我没有取得多大进展。简短回答:你不能 详细回答: List convertierabletolist(Iterable Iterable)的类型E通常不可重新定

假设我有一个方法:

public class AwesomeClass {

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

}

到目前为止,我一直在尝试使用番石榴的课程,但我没有取得多大进展。

简短回答:你不能

详细回答:

List convertierabletolist(Iterable Iterable)
的类型
E
通常不可重新定义。您可以检查提供的iterable是否已在其类定义中修复了该类型(1),这意味着您可以检索该类型,并找出
E
在该特定调用中的含义

但在一般情况下,运行时不知道任何特定调用的
E
是什么


(1) 这意味着类似于
类StringList的东西在类型变量固定的地方实现List

因此,这实际上是可能的,前提是您具有方法的实际参数的形式
类型。正如@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);
}

你看了吗??另外,当您知道参数类型,并且可以从参数类型中扣除退货时,您为什么要再次检查退货类型?@Smutje:我在那个问题上花了很多时间,但它似乎没有解决这个问题。如果我理解正确,他们试图在运行时从对象中获取通用信息。我提供的代码只是一个单元测试,演示了我试图实现的目标。实际生产代码将不知道预期的返回类型。生产代码将使用
resolveReturnType
来告诉它,给定其参数类型,方法的返回类型是什么。你看过Javadoc了吗?但是,再说一遍,为什么你要重新计算一些已知的东西呢?@LouisWasserman:我看过
resolveType
,我已经研究了一个晚上,但我还没能让它以我想要的方式解决(非常好而且简洁!我希望我也能因为解析实例类型参数而奖励积分。我太专注于
TypeToken.resolveType
方法了,以至于我完全忽略了它的
getSuperclass
方法。还有一件事没有正确处理,那就是一个类型变量有多个实例的情况参数中的e:
TypeResolver
在第二次尝试将类型变量映射到实类型时抛出异常,即使两次的实类型都相同。这可能通过捕获
IllegalArgumentException
或(更麻烦的是)重新实现
TypeResolver
来解决。
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);
}
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));
  }
}