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));
}
}