正如您所知,Spring 4 中有一个新功能:基于通用类型的自动装配。
这是非常有用的,但我想知道,Spring 的开发人员是如何绕过类型擦除的,这曾经阻止他们开发这样的功能。
(注意:保留了原文中的 标签)
正如您所知,Spring 4 中有一个新功能:基于通用类型的自动装配。
这是非常有用的,但我想知道,Spring 的开发人员是如何绕过类型擦除的,这曾经阻止他们开发这样的功能。
(注意:保留了原文中的 标签)
擦除意味着信息从运行时中消失。它仍然存在于编译时的信息中,您可以通过反射访问它。在粗略的级别上,您可以认为有关个别实例的通用信息已被删除,但有关类的通用信息并未被删除。
例如,这里有一个简单的程序,定义了一个泛型方法foo
,然后从main
中打印出有关它的泛型信息:
import java.util.*;
import java.lang.reflect.*;
public class GenericReflection {
public static void main(String[] args) throws Exception {
Method m = GenericReflection.class.getDeclaredMethod("foo");
System.out.println(m.getGenericReturnType());
}
public static List<String> foo() {
return null;
}
}
输出:
java.util.List<java.lang.String>
正如您所看到的,一旦深入了解,它并不太复杂。
Method.getGenericReturnType
返回一个 java.lang.reflect.Type
,它有一些子类。其中之一是 ParameterizedType
,它有一个方法 getActualTypeArguments
,返回此类型参数化的实际类型。当然,这些类型也可能是泛型的,这就是为什么它返回一个 Type[]
而不是 Class[]
的原因。在上面的 foo
示例中,它将返回一个具有一个元素的数组,表示 String
:
ParameterizedType pm = (ParameterizedType) m.getGenericReturnType();
Type[] pmArgs = pm.getActualTypeArguments();
System.out.println(Arrays.toString(pmArgs));
[class java.lang.String]
类似的“通用”方法也适用于Field.getGenericType
。您可以使用此信息了解List<String>
是参数化为String
的List
,这正是他们需要的信息。
getActualTypeArguments()
? - PatisonResolvableType
,也没有使用过它...但通常是这样做的。我的回答的主要目的是说明擦除并不意味着从类元数据中抹去所有信息。 - yshavit