泛型(Generic)
泛型允許程序員在強類型程序設計語言中編寫代碼時使用一些以后才指定的類型,在實例化時作為參數指明這些類型。各種程序設計語言和其編譯器、運行環境對泛型的支持均不一樣。Ada、Delphi、Eiffel、Java、C#、F#、Swift 和 Visual Basic .NET 稱之為泛型(generics);ML、Scala 和 Haskell 稱之為參數多態(parametric polymorphism);C++ 和 D稱之為模板。具有廣泛影響的1994年版的《Design Patterns》一書稱之為參數化類型(parameterized type)。
泛型定義及目的
泛型的定義主要有以下兩種:
- 在程序編碼中一些包含類型參數的類型,也就是說泛型的參數只可以代表類,不能代表個別對象。(這是當今較常見的定義)
- 在程序編碼中一些包含參數的類。其參數可以代表類或對象等等。(現在人們大多把這稱作模板)
不論使用哪個定義,泛型的參數在真正使用泛型時都必須作出指明。
一些強類型程序語言支持泛型,其主要目的是加強類型安全及減少類轉換的次數,但一些支持泛型的程序語言只能達到部分目的。
泛型類、泛型接口、泛型方法可參考鏈接:泛型
如何獲取泛型類型
通過反射方式獲取
1)通過反射獲取父類對象的類型;
2)判斷是參數化類型還是Class類型,如果是Class類型則獲取父類的父類對象類型;
3)拿到參數化類型,獲取該類型中的泛型類型;
ParameterizedType是參數化類型,即帶有泛型的類型,比如
List<String>、Set<Long>、Map<String, Long>、Class<Float>
等類型;
其中它有三個方法
- getActualTypeArguments():獲取該類型中的泛型類型;
- getRawType():獲取對應的原始類型,比如
List<String>
類型的原始類型就是List
;- getOwnerType():獲取擁有者的類型,當該類型是內部類的時候,獲取外層類的類型,如果不是內部類則返回的都是null。
import java.lang.ref.ReferenceQueue;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;public class AccessGenericTypeDemo {static class SuperClass<T> {}/*** 強引用: 當一個對象被強引用變量引用時,它處于可達狀態,是不可能被垃圾回收器回收的,即使該對象永遠不會被用到也不會被回收。* 軟引用: 當系統內存充足時它不會被回收,當系統內存不足時它才會被回收。* 弱引用: 只要垃圾回收機制一運行,不管 JVM 的內存空間是否足夠,都會回收該對象占用的內存。* 虛引用: 在任何時候都可能被垃圾回收器回收,它不能單獨使用也不能通過它訪問對象,虛引用必須和引用隊列(RefenenceQueue)聯合使用。*/private static class Clazz extends SuperClass<ReferenceQueue> {}/*** 通過反射方式獲取父類泛型類型*/private static Type getSuperClassGenericType() {// 獲取當前對象的直接父類的類型Type type = Clazz.class.getGenericSuperclass();// ParameterizedType獲取 參數化類型 ,即平常所用到的泛型List<String>、Map<K,V>,Set<T>,Class<?> 數組類型(GenericArrayType)if (type instanceof ParameterizedType) {return ((ParameterizedType) type).getActualTypeArguments()[0];// 兩層繼承} else if (type instanceof Class) {type = ((Class<?>) type).getGenericSuperclass();return ((ParameterizedType) type).getActualTypeArguments()[0];} else {throw new ClassCastException("get class error,actual type is " + Clazz.class.getCanonicalName());}}public static void main(String[] args) {System.out.println(getSuperClassGenericType());}
}
通過Spring框架的ResolvableType獲取
官方文檔鏈接:docs.spring.io —— ResolvableType
import org.springframework.core.ResolvableType;import java.lang.ref.ReferenceQueue;
import java.lang.reflect.Type;public class AccessGenericTypeDemo {static class SuperClass<T> {}private static class Clazz extends SuperClass<ReferenceQueue> {}/*** 通過 org.springframework.core.ResolvableType 獲取父類對象** @return ResolvableType*/private static Type getResolvableType() {return ResolvableType.forClass(Clazz.class).getSuperType().getGeneric(0).resolve();}public static void main(String[] args) {System.out.println(getResolvableType());}
}
兩者獲取結果如下,
擴展
上面Type類型的子類除了Class和ParameterizedType,還有GenericArrayType、TypeVariable、WildcardType,可參考:簡書_Type的幾個接口子類講解