1、Type
Type是一个接口,是所有类型的父类,下图展示了Type的继承结构:
image.png
可以看到Type的子类有如下几个:
- 1、Class:原始类型/基本类型
- 2、ParameterizedType:参数化类型,在声明含有泛型的变量就是参数化类型,无论其中的泛型有没有具体的实现,如List<T> list1,List<String> list2都是参数化类型的。
- 3、TypeVariable:类型变量,其实代表的就是泛型尖括号中的东西,比如List<T>中的T,或者直接声明一个泛型变量如private T t。
- 4、WildcardType:通配符类型
- 5、GenericArrayType:泛型数组类型
2、ParameterizedType:参数化类型
需要注意的是,并不只是 Collection<String> 才是 parameterized,任何类似于 ClassName<V> 这样的类型都是 ParameterizedType ,比如下面的这些都是 parameterizedType.
Map<String, Person> map;
Set<String> set1;
Class<?> clz;
Holder<String> holder;
List<String> list;
而类似于这样的 ClassName 不是 ParameterizedType。
Set set;
List aList;
T t;
2.1、ParameterizedType 的几个主要方法
- Type[] getActualTypeArguments();
- Type getRawType();
- Type getOwnerType();
1、Type[] getActualTypeArguments()
getActualTypeArguments()
获取类型内部的泛型的实际类型,如Map<String,Person> map 返回的是String类型和Person类型组成的Type的数组。
2、Type getRawType()
getRawType()
返回原始类型,如 Map<String,Person> map返回的就是Map类型
3、Type getOwnerType()
getOwnerType()
获取所有者类型,只有内部类才有所有者,如Map.Entry<String, String> entry 的 getOwnerType() 返回的就是Map类型,而Map<String,String>则返回null。
2.2、Demo
public class ParameterizedTypeTest {
private Map<String, ParameterizedTypeTest> map;
private Set<String> set1;
private Class<?> clz;
private Holder<String> holder;
private List<String> list;
private ArrayList<String> arrayList;
private Map.Entry<String, String> entry;
private String str;
private Integer i;
private Set set;
private List aList;
static class Holder<V> {
}
public static void main(String[] args) {
Field f = null;
try {
// 拿到所有的字段
Field[] fields = ParameterizedTypeTest.class.getDeclaredFields();
for (int i = 0; i < fields.length; i++) {
f = fields[i];
if (f.getGenericType() instanceof ParameterizedType) {
ParameterizedType parameterizedType = (ParameterizedType) f.getGenericType();
System.out.println(f.getName() + ":");
System.out.println("\t ParameterizedType:" + Arrays.asList(parameterizedType.getActualTypeArguments()));
System.out.println("\t getRawType:" + parameterizedType.getRawType());
System.out.println("\t getOwnerType:" + parameterizedType.getOwnerType());
}
// 输出不是ParameterizedType 参数化类型的
else {
System.out.println(f.getName() + ":is not ParameterizedType ");
}
}
} catch (Exception e) {
}
}
}
输出:
map:(对应Map<String, ParameterizedTypeTest> map)
ParameterizedType:[class java.lang.String, class com.fsx.maintest.ParameterizedTypeTest]
getRawType:interface java.util.Map
getOwnerType:null
set1:(对应Set<String> set1)
ParameterizedType:[class java.lang.String]
getRawType:interface java.util.Set
getOwnerType:null
clz:(对应Class<?> clz)
ParameterizedType:[?]
getRawType:class java.lang.Class
getOwnerType:null
holder:(对应Holder<String> holder)
ParameterizedType:[class java.lang.String]
getRawType:class com.fsx.maintest.ParameterizedTypeTest$Holder
getOwnerType:class com.fsx.maintest.ParameterizedTypeTest
list:(对应List<String>)
ParameterizedType:[class java.lang.String]
getRawType:interface java.util.List
getOwnerType:null
arrayList:(对应ArrayList<String>)
ParameterizedType:[class java.lang.String]
getRawType:class java.util.ArrayList
getOwnerType:null
entry:(对应Map.Entry<String,String>)
ParameterizedType:[class java.lang.String, class java.lang.String]
getRawType:interface java.util.Map$Entry
getOwnerType:interface java.util.Map
str:is not ParameterizedType
i:is not ParameterizedType
set:is not ParameterizedType
aList:is not ParameterizedType
2、TypeVariable:类型变量
比如 :
public T t,属于类型变量。t属于类型变量。
public class TypeVariableBean<K extends InputStream & Serializable, V> , K和V都是属于类型变量。
public <T> test(T t){}方法中的<T>
以及参数中的T t都属于类型变量。
2.1、TypeVariable的主要方法
- Type[] getBounds(): 得到上边界的Type数组,如K的上边界数组是InputStream 和 Serializable 。V没有指定的话上边界是Object。
- D getGenericDeclaration():返回的是声明该类型变量的实体,如
TypeVariableBean<K extends InputStream & Serializable, V>
中的TypeVariableBean
。 - String getName();返回的是这个type variable的名称。
2.2、Demo
2.2.1、获取类的泛型类型
先定义一个泛型类
public class TestClass<T> {
}
获取该泛型类的泛型的类型
//获取类的泛型的类型
TypeVariable<Class<TestClass>>[] classVariable = TestClass.class.getTypeParameters();
for (TypeVariable<Class<TestClass>> classTypeVariable : classVariable) {
Type[] bounds = classTypeVariable.getBounds();
Class<TestClass> genericDeclaration = classTypeVariable.getGenericDeclaration();
String name = classTypeVariable.getName();
System.out.println("上边界:"+Arrays.toString(bounds));
System.out.println("声明该类型的实体:"+genericDeclaration.getName());
System.out.println("名称:"+name);
}
输出
上边界:[class java.lang.Object]
声明该类型的实体:com.example.abu.serviceproject.TestClass
名称:T
2.2.2、获取类的属性的泛型类型
在TextClass中声明一个类型变量的属性
public class TestClass<T> {
private T t;
}
获取属性的泛型类型
try {
Field field = TestClass.class.getDeclaredField("t");
Type genericType = field.getGenericType();
if (genericType instanceof TypeVariable) {
TypeVariable typeVariable= (TypeVariable) genericType;
Class genericDeclaration = (Class) typeVariable.getGenericDeclaration();
Type[] bounds = typeVariable.getBounds();
String name = typeVariable.getName();
System.out.println("上边界:"+Arrays.toString(bounds));
System.out.println("声明该类型的实体:"+genericDeclaration.getName());
System.out.println("名称:"+name);
}
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
输出
上边界:[class java.lang.Object]
声明该类型的实体:com.example.abu.serviceproject.TestClass
名称:T
2.2.3、获取类的方法的泛型类型
在TestClass中创建一个方法
public class TestClass<T> {
T t;
public <K> void test(T t, K k) {
}
}
可以看到这里我们声明了一个泛型方法test()
,声明了一个泛型<K>
,并且接收两个参数T t
和K k
,这三个都是类型变量类型的,它们有什么区别呢?
Method[] declaredMethods = TestClass.class.getDeclaredMethods();
for (Method declaredMethod : declaredMethods) {
//获取方法定义的泛型类型
TypeVariable<Method>[] typeParameters = declaredMethod.getTypeParameters();
for (TypeVariable<Method> typeParameter : typeParameters) {
Method genericDeclaration = typeParameter.getGenericDeclaration();
Type[] bounds = typeParameter.getBounds();
String name = typeParameter.getName();
System.out.println("方法泛型的名称:" + name+":");
System.out.println("\t方法泛型的上边界:" + Arrays.toString(bounds));
System.out.println("\t方法中声明该类型的实体:" + genericDeclaration.getName());
}
//获取方法参数的泛型类型
Type[] genericParameterTypes = declaredMethod.getGenericParameterTypes();
for (Type genericParameterType : genericParameterTypes) {
if (genericParameterType instanceof TypeVariable) {
TypeVariable typeVariable = (TypeVariable) genericParameterType;
GenericDeclaration genericDeclaration = typeVariable.getGenericDeclaration();
Type[] bounds = typeVariable.getBounds();
String name = typeVariable.getName();
System.out.println("方法中参数泛型的名称:" + name + ":");
System.out.println("\t方法参数中泛型的上边界:" + Arrays.toString(bounds));
if (genericDeclaration instanceof Class)
System.out.println("\t方法中参数声明该类型的实体:" + ((Class) genericDeclaration).getName());
else if (genericDeclaration instanceof Method)
System.out.println("\t方法中参数声明该类型的实体:" + ((Method) genericDeclaration).getName());
}
}
}
输出
方法泛型的名称:K:
方法泛型的上边界:[class java.lang.Object]
方法中声明该类型的实体:test
方法中参数泛型的名称:T:
方法参数中泛型的上边界:[class java.lang.Object]
方法中参数声明该类型的实体:com.example.abu.serviceproject.TestClass
方法中参数泛型的名称:K:
方法参数中泛型的上边界:[class java.lang.Object]
方法中参数声明该类型的实体:test
我们在class TestClass<T>
泛型类中声明了一个泛型方法<K> void test(T t, K k)
。
-
Method.getTypeParameters()
:返回的是定义在泛型方法上泛型类型的数组,对于泛型方法<K> void test(T t, K k)
来说就是K。由于是泛型是声明在方法上的所以getGenericDeclaration
返回的就是Method test() -
Method.getGenericParameterTypes()
:返回的是方法中参数的泛型类型,test()
方法有T t, K k
两个参数,由于T
是声明在TestClass
上的,K
是声明在方法上的,所以对于T getGenericDeclaration
返回的就是Class TestClass,而对于K getGenericDeclaration
返回的就是Method test()。
3、GenericArrayType:泛型数组
GenericArrayType是泛型数组,组成数组的元素中有泛型的数组就是GenericArrayType类型的,组成数组的元素可以是ParameterizedType类型的也可以是TypeVariable类型的。
// 属于 GenericArrayType 组成元素是ParameterizedType
List<String>[] pTypeArray;
// 属于 GenericArrayType 组成元素是TypeVariable
T[] vTypeArray;
// 不属于 GenericArrayType
List<String> list;
// 不属于 GenericArrayType
String[] strings;
// 不属于 GenericArrayType
Person[] ints;
Demo
public class TestClass<T> {
T[] t;
TestClass<T>[] testClassArray;
List<String>[] listArray;
String[] strArray;
}
获取类中的属性是否是泛型数组类型,并获取数组中元素的类型。
public void test() {
Field[] declaredFields = TestClass.class.getDeclaredFields();
for (Field declaredField : declaredFields) {
Type genericType = declaredField.getGenericType();
String fieldName = declaredField.getName();
if (genericType instanceof GenericArrayType) {
System.out.println("泛型数组:" + fieldName + ":");
GenericArrayType genericArrayType= (GenericArrayType) genericType;
Type genericComponentType = genericArrayType.getGenericComponentType();
System.out.println("\t泛型数组中元素的类型:"+genericComponentType);
} else {
System.out.println("非泛型数组:" + fieldName);
}
}
}
输出
泛型数组:t: (对应T[] t)
泛型数组中元素的类型:T
泛型数组:testClassArray:(对应TestClass<T>[] testClassArray)
泛型数组中元素的类型:com.example.abu.serviceproject.TestClass<T>
泛型数组:listArray:(对应List<String>[] listArray)
泛型数组中元素的类型:java.util.List<java.lang.String>
非泛型数组:(对应String[] strArray)strArray
4、WildcardType :通配符类型
<?>、<?extends Number>、<? super Integer>
这些都是通配符类型的,extends 用来指定上边界,没有指定的话上边界默认是 Object, super 用来指定下边界,没有指定的话为 null。
几个主要方法介绍
- Type[] getLowerBounds() 得到上边界 Type 的数组
- Type[] getUpperBounds() 得到下边界 Type 的数组
下面一起来看一下例子。
public class WildcardTypeBean<T> {
private List<? extends Number> a; // a没有下界,
// 没有指定的话,上边界默认是 Object ,下边界是 String
private List<? super String> b;
private List<String> c;
private List<T> list;
private Class<?> aClass;
}
public void testWildCardType() {
Field[] fields = WildcardTypeBean.class.getDeclaredFields();
for (Field field : fields) {
Type genericType = field.getGenericType();
if (genericType instanceof WildcardType)
System.out.println(field.getName() + " is WildcardType");
else if (genericType instanceof ParameterizedType){
System.out.println(field.getName() + " is ParameterizedType");
ParameterizedType parameterizedType= (ParameterizedType) genericType;
Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
Type actualTypeArgument=actualTypeArguments[0];
if(actualTypeArgument instanceof WildcardType){
WildcardType wildcardType= (WildcardType) actualTypeArgument;
System.out.println("-----------------通配符类型-----------------");
System.out.println("name:"+wildcardType.getTypeName());
System.out.println("上边界:"+Arrays.toString(wildcardType.getUpperBounds()));
System.out.println("下边界:"+Arrays.toString(wildcardType.getLowerBounds()));
}else if(actualTypeArgument instanceof ParameterizedType){
System.out.println("-----------------参数化类型-----------------");
System.out.println("name:"+actualTypeArgument.getTypeName());
}else if(actualTypeArgument instanceof TypeVariable){
System.out.println("-----------------类型变量-----------------");
System.out.println("name:"+actualTypeArgument.getTypeName());
}else if(actualTypeArgument instanceof Class){
System.out.println("-----------------原始类型-----------------");
System.out.println("name:"+actualTypeArgument.getTypeName());
}
}
}
}
输出
a is ParameterizedType
-----------------通配符类型-----------------
name:? extends java.lang.Number
上边界:[class java.lang.Number]
下边界:[]
b is ParameterizedType
-----------------通配符类型-----------------
name:? super java.lang.String
上边界:[class java.lang.Object]
下边界:[class java.lang.String]
c is ParameterizedType
-----------------原始类型-----------------
name:java.lang.String
list is ParameterizedType
-----------------类型变量-----------------
name:T
aClass is ParameterizedType
-----------------通配符类型-----------------
name:?
上边界:[class java.lang.Object]
下边界:[]
网友评论