欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

java 反射 泛型机制 获得泛型的实际类型(二)

程序员文章站 2022-05-13 11:12:25
...
  
   二、 ParameterizedType 参数化的类型,顾名思义,就是给一个类型传递了类型参数,例 List<Contract>  List接口被传递了Contract类型参数,那么类型List<Contract>就是ParameterizedType,它可以做属性的类型,做方法参数或返回值的类型,也可以做泛型声明的上边界。 例如 public class GenericClass<T extends List<Contract>>里的List<Contract>。由于泛型声明可以声明多个泛型参数,所以,参数化的类型也可以传入多个类型参数,多个类型参数用,隔开。例如著名的Map定义的泛型参数是K和V 可以传入Map<String,Contract>等等.如果属性或方法参数声明的数据给类型传递了类型参数,则field.getGenericType method.getGenericParameterType返回Type 就是 instanceof ParameterizedType. ptype.getActualTypeArguments() :Type[]返回每个传入的类型参数,返回值的长度取决于泛型声明时声明了几个形式泛型参数。本文提出的问题便是基于这一点来尝试解决的。ptype.getRawType() type返回的是<>外的类型 即接收类型参数的类型,如List,Map.
  
   三、WildcardType 这种类型用来处理参数化类型里,对类型参数范围的描述。例如一个方法的泛型参数是 Map<? extends Number,? super Contract>,此时 <> 里用逗号隔开两个对象都是WildcardType的实例。对每一个WildcardType对象(验证type instanceof WildcardType==true) wtype.getUpperBounds():Type[]返回上边界类型(默认是Object.class),wtype.getLowerBounds():Type[]返回下边界类型。

  说了这么多,逻辑太绕了,本来就很难说清楚。只有多测试多使用才能体会到。下面给一个我写的方法,这个方法用来访问一个Collection接口类型的Field,假定该Field使用了泛型,然后返回Collection的类型参数具体是什么,即返回客户类指定的集合元素的类型。注意,的确只能在运行时才能确定具体类型,本方法只能获得泛型的边界,然后用上边界类型来构造对象。如果一个使用了泛型的属性刚好就像List<Contract>一样,那么读取到Contract.class是轻而易举的,因为这个泛型参数的边界是固定的。
   public Class getGenericTypeBounds(Field field)
throws TypeResolveException{
Type type = field.getGenericType();
if(type instanceof Class){
throw new TypeResolveException(field.getDeclaringClass().getName()+"属性"
+field.getName()+" 没有使用泛型或者 使用了rawtype但是没有指定泛型实参。");
}
else if(type instanceof GenericArrayType){
type = ((GenericArrayType)type).getGenericComponentType();
}
else if(type instanceof TypeVariable<?>){
type = ((TypeVariable<?>)type).getBounds()[0];
}
else if(type instanceof ParameterizedType){
ParameterizedType ptype = (ParameterizedType)type;
Type[] types = ptype.getActualTypeArguments();
if(types==null || types.length==0){
throw new TypeResolveException(field.getDeclaringClass().getName()+"的集合属性"
+field.getName()+" 所引用的泛型类型没有指定泛型实参取值。");
}
if(types.length>1){
throw new TypeResolveException(field.getDeclaringClass().getName()+"的集合属性"
+field.getName()+" 所引用的泛型类型 指定的泛型实参取值多于1个。");
}
type = ptype.getActualTypeArguments()[0];//只有这个方法的返回值才可能是  WildcardType
}
while(!(type instanceof Class)){
if(type instanceof WildcardType){
type = ((WildcardType)type).getUpperBounds()[0];
}
else if(type instanceof TypeVariable<?>){
type = ((TypeVariable<?>)type).getBounds()[0];
}
else if(type instanceof ParameterizedType){
ParameterizedType ptype = (ParameterizedType)type;
Type[] types = ptype.getActualTypeArguments();
if(types==null||types.length==0){
return Object.class;
}
if(types.length>1){
throw new TypeResolveException(field.getDeclaringClass().getName()+"的集合属性"
+field.getName()+"引用到的泛型"+ptype+"的实参数量多于1个");
}
type = ptype.getActualTypeArguments()[0];
}
else if(type instanceof GenericArrayType ){
type = ((GenericArrayType)type).getGenericComponentType();
}
}
return (Class)type;
}