java中所有的类型都继承自Type
其中包括Class
类也是继承自它,另外它还有四个重要的子类
ParameterizedType
表示是个带泛型的类型,如List<String>
、List<T>
,通过该类型的getActualTypeArguments()
方法可获取到下面三个类型,也有可能获取到Class类型GenericArrayType
表示是个泛型数组,如List<String>[]
、List<T>[]
TypeVariable
表示泛型变量,如public <T> void method(T t)
中的T
WildcardType
表示通配符,如public void method(List<?> arg)
中的?
ParameterizedType
示例
方法签名如下所示
public <T> void genericMethod(List<T> arg1, List<T[]> arg2,
String arg3, Son1 arg4,
Parent arg5, Parent<?> arg6,
Parent<?>[] arg7) {
}
static class Parent<T> {
}
static class Son1 extends Parent<String> {
}
如果调用Method
的getGenericParameterTypes()
可获取到带泛型的参数
- arg1是
ParameterizedType
,如果调用该类型的getActualTypeArguments()
即可获取到T
它的类型是TypeVariable
类型 - arg2是
ParameterizedType
,如果调用该类型的getActualTypeArguments()
即可获取到T[]
它的类型是GenericArrayType
类型 - arg3是
Class
类型 - arg4是
Class
类型 - arg5是
Class
类型 - arg6是
ParameterizedType
类型,如果调用该类型的getActualTypeArguments()
即可获取到?
它的类型是WildcardType
类型 - arg7是
GenericArrayType
类型,如果调用该类型的getGenericComponentType()
即可获取到ParameterizedType
因为getGenericComponentType()
返回的是数组的实际类型,而arg7的实际类型也是一个泛型参数
注意点
在使用的时候应注意局部变量是获取不到泛型的类型的,对于类来说只能获取其父类的泛型类型,而不能获取本类的泛型参数
List<String> arr = new ArrayList<>();
System.out.println(arr.getClass().getGenericSuperclass());
对于上面的代码,由于arr是局部变量,所以是获取不到泛型中的String
的,而Class
的getGenericSuperclass()
方法也只能获取父类的泛型参数,对于上面这个代码获取到的类型是java.util.AbstractList<E>
它的类型是ParameterizedType
对于前面ParameterizedType
示例中代码的Son1
类来说,可以获取到其指定的泛型类型String
获取的方法也很简单System.out.println(((ParameterizedType) Son1.class.getGenericSuperclass()).getActualTypeArguments()[0])
因为我们已知在子类继承父类时指定了泛型,所以其类型就是ParameterizedType
,那为什么不能是其他三个呢?
为什么不能是GenericArrayType
比如GenericArrayType
为什么不能是它?如果你有这个疑惑那肯定是没能理解什么情况下才是那个类型,我们说只有当这个参数是个数组时才是这个类型, 很明显我们子类继承父类的时候不能继承一个数组,这里给出两个示例,一个正确的,一个错误的
这是正确的,我们继承自List,其里面的泛型指定为String[]数组,但是请注意,这种泛型的类型为ParameterizedType
而不是GenericArrayType
,因为GenericArrayType
的格式是List<String>[]这样才是GenericArrayType
类型
public class Son extends List<String[]> {}
如果java支持这中形式的继承的话那它的类型应该是GenericArrayType
但是java不支持,这种一种语法错误
public class Son extends List<String>[] {}
为什么不能是TypeVariable
那为什么不能是TypeVariable
?其实也很简单,TypeVariable
类型代表的是泛型本身,如:public <T> void method(T t){}
中的 T
,那我们继承的时候能继承自泛型吗? 比如 public class Son<T> extends T {}
很明显也是错误的
为什么不能是WildcardType
有了上面两个案例,相信你这里应该很清楚了,WildcardType
表示的是一种通配符,比如public void method(List<?> arag1){}
中的 ?
类继承的时候能继承自通配符?
吗?很显然不能
所以最后的结论就是如果调用类的getGenericSuperclass()
方法其返回的类型一定是Class
类型,或者是ParameterizedType
关键就是看继承父类时有没有指定泛型,如果有指定泛型则是ParameterizedType
类型,如果没有则是Class
类型