Type类型详解

什么是Type?

引用网上的话来说就是:
Type是一个空接口,所有类型的公共接口(父接口),其意义表示Java所有类型,这里所谓的类型是从Java整个语言角度来看的,比如原始类型、参数化类型(泛型)、类型变量及其数组等,可以理解为,Class(类)是Java对现实对象的抽象,而Type是对Java语言对象的抽象。

Type的类型

实现了Type接口的子接口为GenericArrayType(泛型数组类型),ParmeterizedType(参数化类型),TypeVariable<D>(类型变量),WildcardType(通配符类型)。实现了Type接口的子类有Class(类)。所有Type一共可以表示这5类数据。主要介绍的就是四个子接口。

Type的用处

 由于java1.5引入了泛型这一概念,大大方便了我们代码的编写和优化,但是考虑到泛型擦除这一问题,当我们的代码在运行时期会擦除所有的泛型,这一我们在运行时期想要获取某一类原来是带有泛型的,而后来被擦除了的数据的泛型类型时就会有问题。所以java引入了Type这一概念。Type也主要是为在运行时期获取泛型而服务。

接下来,我们开始介绍泛型中各子接口和子类的作用,在开始介绍之前我们了解一下编码过程中主要的运用到泛型的情况。
1.List<T>
2.Set<T> 
3.Map<K,V>
4.class<?>(自定义类或接口的泛型)

ParmeterizedType(参数化类型)的作用

    parameterizedType主要是用来表示 如 Collection<String>或者Class<T>。 parameterizedType表示的类型非常的简单,只要带着泛型,除了不可以是数组和本类上定义的泛型以外,其他都被列入ParameterizedType的范围。

ParameterizedType的主要方法:

Type[] getActualTypeArguments()
         返回表示此类型实际类型参数的 Type 对象的数组。

 Type getOwnerType()

         返回 Type 对象,表示此类型是其成员之一的类型。

 Type getRawType()

          返回 Type 对象,表示声明此类型的类或接口。
接下来我们来看一个例子。
示例一:
现在有三个类,分别为Person,TypeBean以及ParameterizedTypeTest
Person类
public class Person {
	@Override
	public String toString() {
		return "Person []";
	}
	 class Animal <T> {
		public String name;
	}
}

TypeBean类
public class TypeBean<T> {
	public  List<String> list;
	private  Set<String>[] set;
	private  List noGerList;
	Map.Entry<String,Integer> entry;
	Person.Animal<String> animal;
	String str = new String();
	T t;
}


ParameterizedTypeTest类
public class ParameterizedTypeTest{
	public static void main(String[] args) throws Exception {
		Class<TypeBean> bean = (Class<TypeBean>) Class.forName("TypeBean");
		Field[] declaredFields = bean.getDeclaredFields();
		int i =1;
		for (Field field : declaredFields) {
			field.setAccessible(true);
			System.out.println("--------------"+i);
			System.out.println("field name is : "+field.getName());
			 System.out.print("field.getGenericType() instanceof ParameterizedType");
			 System.out.println("--------"+(field.getGenericType() instanceof ParameterizedType));
			 if(field.getName().equals("animal")){
				 ParameterizedType type = (ParameterizedType) field.getGenericType();
				 Type ownerType = type.getOwnerType();
				 System.out.println("Person.Animal<String>的ownerType是。。。"+ownerType);
				 Type rawType = type.getRawType();
				 System.out.println("Person.Animal<String>的rawType是"+rawType);
				 Type[] actualTypeArguments = type.getActualTypeArguments();
				 for (Type type2 : actualTypeArguments) {
					System.out.println(type2.getTypeName()+"获取到的actualTypeArguments分别为:"+type2.getTypeName());
				}
				 System.out.println("Person.Animal<String> instanceof ParameterizedType -----"+(type instanceof ParameterizedType));
			 }
			 System.out.println("--------------"+i);
			i++;
			
		}
	}
}


运行 ParameterizedTypeTest类得到的结果如下。
--------------1
field name is : list
field.getGenericType() instanceof ParameterizedType--------true
--------------1
--------------2
field name is : set
field.getGenericType() instanceof ParameterizedType--------false
--------------2
--------------3
field name is : noGerList
field.getGenericType() instanceof ParameterizedType--------false
--------------3
--------------4
field name is : entry
field.getGenericType() instanceof ParameterizedType--------true
--------------4
--------------5
field name is : animal
field.getGenericType() instanceof ParameterizedType--------true
Person.Animal<String>的ownerType是。。。class Person
Person.Animal<String>的rawType是class Person$Animal
java.lang.String获取到的actualTypeArguments分别为:java.lang.String
Person.Animal<String> instanceof ParameterizedType -----true
--------------5
--------------6
field name is : str
field.getGenericType() instanceof ParameterizedType--------false
--------------6
--------------7
field name is : t
field.getGenericType() instanceof ParameterizedType--------false
--------------7
第一个字段List<String> list 是ParameterizedType。
第二个字段Set<String>[] set由于是数组,所以不是ParameterizedType。
第三个字段List noGerList由于没有带泛型,所以也不是ParameterizedType。
第四个字段Map.Entry<String,Integer> entry 是parameterizedType。
第五个字段Person.Animal<String> animal 是parameterizedType。此处我们进一步使用了ParameterizedType的3个方法演示给大家看。我们可以看到ownerType是animal的外部类Person。这也印证了获取到的类型(Person)为原类型(Person.Animal)是其(Person)成员之一。(这里还有其他情况欢迎在评论区告诉。
而rawType则是其自身类型。
getActualTypeArguments()获取到的Type数组则是泛型中的所有类型。(例如Map<k,v>则获取到的数组中包含k,v这两个类型。并且k在前,v在后。)
第六个字段String str = new String();由于没有带泛型所有不是parameterizedType。
第七个字段T t 由于是本类上定义的泛型,所以也不行。

TypeVariable<D>(类型变量)的作用

TypeVariable 是各种类型变量的公共高级接口。类型变量在反射方法首次需要时创建(在此包中指定)。如果类型变量 t 由类型(即类、接口或注释类型)T 引用,而且 T 由 T 的第 n 个封闭类声明(请参见 JLS 8.1.2),那么创建 t 需要解析(请参见 JVMS 5)T 的第 i 个封闭类,其中 i = 0 到 n(包含)。创建某个类型变量决不能导致创建其边界。重复创建类型变量没有效果。

可以在运行时将多个对象实例化,以表示一个给定的类型变量。尽管类型变量仅创建一次,这并不意味着任何缓存实例的要求都表示类型变量。不过,表示类型变量的所有实例彼此必须相等 (equal())。因此,使用类型变量的用户决不能依靠实现此接口的类实例的身份。


这是api中的介绍,其实非常简单。这就是我们非常常用的声明类时的泛型。

例如: 
public class Test<T>{

}
这里的T的类型就属于TypeVariable。(注:T不能为数组。)

TypeVariable的主要方法

Type[] getBounds() 
          返回表示此类型变量上边界的 Type 对象的数组。如上边界未显式声明,则为Object。
 D getGenericDeclaration() 
          返回 GenericDeclaration 对象,该对象表示声明此类型变量的一般声明。 
 String getName() 
          返回此类型变量的名称,它出现在源代码中。
 示例二: 
 
现在有3个类 Person,TypeVariableBean,TypeVariableTest
TypeVariableBean类
public class TypeVariableBean<T> {
	public  List<String> list;
	Class<?> clz;
	private  Set<String>[] set;
	private  List noGerList;
	Map.Entry<String,Integer> entry;
	Person.Animal<String> animal;
	String str = new String();
	T t;
}
Person类
public class Person {	
	@Override
	public String toString() {
		return "Person []";
	}
	 class Animal <T> {
		public String name;
	}
}
TypeVariableTest类
public class TypeVariableTest {
	public static void main(String[] args) {
		Field[] declaredFields = TypeVariableBean.class.getDeclaredFields();
		for (Field field : declaredFields) {
			field.setAccessible(true);
			Type type = field.getGenericType();
			System.out.println("field.getGenericType() instanceof TypeVariable ? ------ "+(type instanceof TypeVariable));
			if(field.getGenericType() instanceof TypeVariable){
				Type[] bounds = ((TypeVariable) type).getBounds();
				int i = 0;
				for (Type type2 : bounds) {
					System.out.println("------------"+i);
					System.out.println("上边界是:"+type2.getTypeName());
					System.out.println("------------"+i);
					i++;
				}
				GenericDeclaration genericDeclaration = ((TypeVariable) type).getGenericDeclaration();
				System.out.println("TypeeVariable's Name::::"+((TypeVariable) type).getName());
				System.out.println(genericDeclaration);
			}
		}
	}
}


此时我们运行TypeVariableTest类时。得到的结果是:
field.getGenericType() instanceof TypeVariable ? ------ false
field.getGenericType() instanceof TypeVariable ? ------ false
field.getGenericType() instanceof TypeVariable ? ------ false
field.getGenericType() instanceof TypeVariable ? ------ false
field.getGenericType() instanceof TypeVariable ? ------ false
field.getGenericType() instanceof TypeVariable ? ------ false
field.getGenericType() instanceof TypeVariable ? ------ false
field.getGenericType() instanceof TypeVariable ? ------ true
------------0
上边界是:java.lang.Object
------------0
TypeeVariable's Name::::T
class TypeVariableBean
我们可以看出,只有最后一个是我们自己在类上定义的泛型时才是TypeVariable。此时的上边界是Object,因为我们没有显式的定义其上边界,现在我们改变一下TypeVariableBean这个类的泛型上边界。
更改后的TypeVariableBean类
public class TypeVariableBean<T extends Person & Serializable> {
	public  List<String> list;
	Class<?> clz;
	private  Set<String>[] set;
	private  List noGerList;
	Map.Entry<String,Integer> entry;
	Person.Animal<String> animal;
	String str = new String();
	T t;
}
这时我们运行的结果如下
field.getGenericType() instanceof TypeVariable ? ------ false
field.getGenericType() instanceof TypeVariable ? ------ false
field.getGenericType() instanceof TypeVariable ? ------ false
field.getGenericType() instanceof TypeVariable ? ------ false
field.getGenericType() instanceof TypeVariable ? ------ false
field.getGenericType() instanceof TypeVariable ? ------ false
field.getGenericType() instanceof TypeVariable ? ------ false
field.getGenericType() instanceof TypeVariable ? ------ true
------------0
上边界是:Person
------------0
------------1
上边界是:java.io.Serializable
------------1
TypeeVariable's Name::::T
class TypeVariableBean
这时就出现了两个上边界。

GenericArrayType(泛型数组类型)的作用

顾名思义,只有是带泛型的,并且是数组的那就属于GenericArrayType的范畴。

GenericArrayType的主要方法:

Type	getGenericComponentType() 
          返回表示此数组的组件类型的 Type 对象。
示例三:
有四个类 Person ,PersonInterface,GenericArrayTypeBean,GenericArrayTypeTest
Person类
public class Person {	
	@Override
	public String toString() {
		return "Person []";
	}
	 class Animal <T> {
		public String name;
	}
}


PersonInterface类
public interface PersonInterface {
}
GenericArrayTypeBean类
public class GenericArrayTypeTest {
	public static void main(String[] args) {
		Field[] fields = GenericArrayTypeBean.class.getDeclaredFields();
		int i =1;
		for (Field field : fields) {
			Type type = field.getGenericType();	
			System.out.println("----------"+i);
				if(type instanceof ParameterizedType){
					System.out.println(type.getTypeName());
					System.out.println("field.getGenericType() instanceof ParameterizedType::");
				}else if(type instanceof TypeVariable){
					System.out.println(type.getTypeName());
					System.out.println("field.getGenericType() instanceof TypeVariable::");
				}else if(type instanceof GenericArrayType){
					System.out.println(type.getTypeName());
					System.out.println("field.getGenericType() instanceof GenericArrayType::");
					Type genericComponentType = ((GenericArrayType) type).getGenericComponentType();
					System.out.println(type.getTypeName()+"数组的组成为:"+genericComponentType.getTypeName());
				}else if(type instanceof Class){
					System.out.println(type.getTypeName());
					System.out.println("field.getGenericType() instanceof Class::");
				}else{
					System.out.println(type.getTypeName()+" instanceof "+type.getClass());
				}
				System.out.println("----------"+i);
				i++;	
		}
	}
}
运行GenericArrayTypeTest类的结果为:
----------1
java.util.List<Person>[]
field.getGenericType() instanceof GenericArrayType::
java.util.List<Person>[]数组的组成为:java.util.List<Person>
----------1
----------2
java.util.Set<K>
field.getGenericType() instanceof ParameterizedType::
----------2
----------3
java.util.Map<K, V>
field.getGenericType() instanceof ParameterizedType::
----------3
----------4
java.util.List<Person>
field.getGenericType() instanceof ParameterizedType::
----------4
----------5
K
field.getGenericType() instanceof TypeVariable::
----------5
----------6
K[]
field.getGenericType() instanceof GenericArrayType::
K[]数组的组成为:K
----------6
----------7
Person
field.getGenericType() instanceof Class::
----------7
----------8
java.lang.String
field.getGenericType() instanceof Class::
----------8
----------9
PersonInterface
field.getGenericType() instanceof Class::
----------9
由此我们可以看出只要是带泛型,并且是数组的就属于GenericArrayType。并且getGenericComponentType方法就是获得该数组的组成类型。

WildcardType(通配符类型)的作用

表示通配符类型参数。

WildcardType是依托于ParameterizedType和GenericArrayTypeTest而存在的。

示例如下:

Class<?>
List<? extends Number>
Set<? super T>

WildcardType的主要方法

 Type[] getLowerBounds() 
          返回表示此类型变量下边界的 Type 对象的数组。 
 Type[] getUpperBounds() 
          返回表示此类型变量上边界的 Type 对象的数组。 


这个类型比较好理解,直接上例子
示例四:WildcardTypeBean,WildcardTypeTest
WildcardTypeBean类
public class WildcardTypeBean<K extends Number & Serializable,V> {
	List<? extends Person>[] list;
	Set<? super Man> set; 
	K k;
}
WildcardTypeTest类
public class WildcardTypeTest {
	public static void main(String[] args) throws Exception{
		Field[] fields = WildcardTypeBean.class.getDeclaredFields();
		for (int i = 0; i <fields.length; i++) {
			System.out.println("--------------"+(i+1));
			Field field = fields[i];
			System.out.println("file:"+field);
			Type type = field.getGenericType();
			if(type instanceof GenericArrayType){
				GenericArrayType gat = (GenericArrayType)type;
				ParameterizedType genericComponentType = (ParameterizedType)gat.getGenericComponentType();
				Type[] actualTypeArguments = genericComponentType.getActualTypeArguments();
				WildcardType t = (WildcardType)actualTypeArguments[0];
				Type[] upperBounds = t.getUpperBounds();
				for (Type type2 : upperBounds) {
					System.out.println("upperBounds:"+type2.getTypeName());
				}
				Type[] lowerBounds = t.getLowerBounds();
				for (Type type2 : lowerBounds) {
					System.out.println("lowerBounds:"+type2.getTypeName());
				}
			}else if(type instanceof ParameterizedType){
				WildcardType wildcardType = ((WildcardType)((ParameterizedType) type).getActualTypeArguments()[0]);
				Type[] lowerBounds = wildcardType.getLowerBounds();
				for (Type type2 : lowerBounds) {
					System.out.println("lowerBounds:"+type2.getTypeName());
				}
			}else{
				System.out.println(type.getTypeName()+" instanceof "+type.getClass());
			}
			System.out.println("--------------"+(i+1));
		}
}


运行结果:
--------------1
file:java.util.List[] WildcardTypeBean.list
upperBounds:Person
--------------1
--------------2
file:java.util.Set WildcardTypeBean.set
lowerBounds:Man
--------------2
--------------3
file:java.lang.Number WildcardTypeBean.k
K instanceof class sun.reflect.generics.reflectiveObjects.TypeVariableImpl
--------------3
到此,Type的四个子接口就基本介绍完毕了。如果有错误的地方,欢迎各位大牛在评论区指出!!!








































猜你喜欢

转载自blog.csdn.net/qq_30770095/article/details/79016257