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的四個子接口就基本介紹完畢了。如果有錯誤的地方,歡迎各位大牛在評論區指出!!!








































發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章