掃二維碼與項(xiàng)目經(jīng)理溝通
我們在微信上24小時(shí)期待你的聲音
解答本文疑問/技術(shù)咨詢/運(yùn)營咨詢/技術(shù)建議/互聯(lián)網(wǎng)交流
本文轉(zhuǎn)載自微信公眾號(hào)「潛行前行」,作者cscw 。轉(zhuǎn)載本文請(qǐng)聯(lián)系潛行前行公眾號(hào)。

創(chuàng)新互聯(lián)建站專業(yè)為企業(yè)提供蘆山網(wǎng)站建設(shè)、蘆山做網(wǎng)站、蘆山網(wǎng)站設(shè)計(jì)、蘆山網(wǎng)站制作等企業(yè)網(wǎng)站建設(shè)、網(wǎng)頁設(shè)計(jì)與制作、蘆山企業(yè)網(wǎng)站模板建站服務(wù),10年蘆山做網(wǎng)站經(jīng)驗(yàn),不只是建網(wǎng)站,更提供有價(jià)值的思路和整體網(wǎng)絡(luò)服務(wù)。
1 JAVA的Type類型體系
先了解下java的Type類型體系(類的類=>類型),Type是所有類型(原生類型-Class、參數(shù)化類型-Parameterizedtype、數(shù)組類型-GenericArrayType、類型變量-TypeVariable、基本類型-Class)的共同接口;前兩篇反射和注解講到的Class 就是Type的一實(shí)現(xiàn)類
2 泛型的概念
泛型: 把類型明確的工作推遲到創(chuàng)建對(duì)象或調(diào)用方法的時(shí)候才去明確的特殊的類型
3 泛型類和泛型方法的示例
- public class MainTest
{ - private T param;
- }
- public static void main(String[] args){
- MainTest
data = new MainTest (){}; - ParameterizedType genType1 = (ParameterizedType)data.getClass().getGenericSuperclass();
- }
- public class MainTest{
- public static void main(String[] args){
- printData("siting");
- }
- static
T printData(T t){ - System.out.println(t);
- return t;
- }
- }
接口和抽象類都可以使用泛型
4 類型擦除
- public class MainTest {
- public static void main(String[] args){
- List
strArr = new ArrayList<>(); - List
intArr = new ArrayList<>(); - Type strClazz = strArr.getClass();
- Type intClazz = intArr.getClass();
- }
- }
- public class MainTest
{ - T param;
- public static void main(String[] args){
- MainTest
test = new MainTest<>(); - test.setParam("siting");
- }
- public T getParam() { return param; }
- public void setParam(T param) { this.param = param; }
- }
- public class com/MainTest {
- ...省略
- public static main([Ljava/lang/String;)V
- L0
- LINENUMBER 7 L0
- NEW com/MainTest
- DUP
- INVOKESPECIAL com/MainTest.
()V - ASTORE 1
- L1
- LINENUMBER 8 L1
- ALOAD 1
- LDC "siting" // 調(diào)用類型擦除后的setParam(Object)
- INVOKEVIRTUAL com/MainTest.setParam (Ljava/lang/Object;)V
- L2
- ...省略//getParam 的返回值是Object
- public getParam()Ljava/lang/Object;
- L0
- LINENUMBER 10 L0
- ALOAD 0
- GETFIELD com/MainTest.param : Ljava/lang/Object;
- ARETURN
- ...省略//setParam 的入?yún)⑹荗bject
- public setParam(Ljava/lang/Object;)V
- L0
- LINENUMBER 11 L0
- ALOAD 0
- ALOAD 1
- PUTFIELD com/MainTest.param : Ljava/lang/Object;
- RETURN
- ...
- }
可以看出T(String)都被轉(zhuǎn)換為Object類型,最初的初始化的String不見了
5 泛型的繼承
- public class MainTest
{ - T param;
- static public class SubTest1 extends MainTest
{} - static public class SubTest2
extends MainTest {} - //SubTest3繼承的時(shí)原生類型
- static public class SubTest3 extends MainTest{}
- }
6 泛型變量TypeVariable
- public class MainTest
{ - List
param; - public static void main(String[] args) throws Exception{
- Class clazz = MainTest.class;
- TypeVariable[] typeVariable = clazz.getTypeParameters();
- // 1
- Field field = clazz.getDeclaredField("param");
- ParameterizedType arrayType = (ParameterizedType)field.getGenericType();
- // interface List
的泛型類型E被T,具體化,因此其被識(shí)別為 TypeVariable - TypeVariable variable1 = (TypeVariable)arrayType.getActualTypeArguments()[0];
- // 2
- ParameterizedType type = (ParameterizedType)SubTest.class.getGenericSuperclass();
- TypeVariable variable2 = (TypeVariable)type.getActualTypeArguments()[0];
- }
- static class SubTest
extends MainTest {} - }
7 參數(shù)化類型ParameterizedType
- public interface ParameterizedType extends Type {
- //獲取實(shí)際參數(shù),List
里的String; 如果是List 則是TypeVariable類型 - Type[] getActualTypeArguments();
- // 獲取原始類型List
-> List - Type getRawType();
- Type getOwnerType();
- }
- public class MainTest
{ - public static void main(String[] args){
- MainTest
str = new MainTest (); - Class variable = str.getClass();
- Type genType1 = variable.getGenericSuperclass();
- }
- }
- // 1 子類繼承泛型時(shí),指定具體參數(shù)(可以是String等已知類型,也可以是子類的泛型參數(shù))
- // 2 獲取在類內(nèi)部定義的泛型屬性,需指定具體泛型參數(shù)
- // 3 局部代碼,可以通過泛型的匿名內(nèi)部子類(需指定具體泛型參數(shù))獲取ParameterizedType類型
- public class MainTest
{ - List
list; - public static void main(String[] args) throws NoSuchFieldException {
- SubTest
str = new SubTest<>(); - // 方式一
- Class variable = str.getClass();
- // 父類是(521)ParameterizedType類型
- ParameterizedType genType = (ParameterizedType)variable.getGenericSuperclass();
- // (521)ParameterizedType類型的原生類型是(479)class com.MainTest
- Type clazz = genType.getRawType();
- //MainTest.class 的原生類型是 (479)class com.MainTest
- Class rawClazz = MainTest.class;
- //方式二,泛型屬性
- Field field = rawClazz.getDeclaredField("list");
- //屬性list 類型是(546)ParameterizedType類型List
- ParameterizedType fieldType = (ParameterizedType)field.getGenericType();
- // 方式三
- MainTest
sub3 = new MainTest (){}; - // clazz3是匿名子類
- Class clazz3 = sub3.getClass();
- //父類是(555)ParameterizedType類型
- ParameterizedType genType3 = (ParameterizedType) clazz3.getGenericSuperclass();
- // (555)ParameterizedType類型的原生類型是(479)class com.MainTest
- Type type3 = genType3.getRawType();
- }
- public static class SubTest
extends MainTest { } - }
8 通配符(WildcardType)
無邊界通配符:無界通配符 ? 可以適配任何引用類型:
- public static void print(List list){}
- ----->>>
- public static void print(List> list){}
上界限定通配符 < ? extends E>
- public static void print(List extends Number> list) {
- Number n = new Double("1.0");
- list.add(n);
- Number tmp = list.get(0);
- }
下界限定通配符 < ? super E>
- class Parent{ }
- class Child extends Parent{ }
- public class MainTest
{ - T param;
- public static void main(String[] args){
- MainTest super Child> parent_m = new MainTest<>();
- parent_m.setParam(new Child());
- Object parent = parent_m.getParam();
- }
- public T getParam() { return param; }
- public void setParam(T param) { this.param = param; }
- }
9 泛型數(shù)組(GenericArrayType)
- public interface GenericArrayType extends Type {
- //獲得這個(gè)數(shù)組元素類型,即獲得:A
(A [])或 T(T[]) - Type getGenericComponentType();
- }
- public class MainTest
{ - T[] param;
- public static void main(String[] args) throws Exception{
- Class clazz = MainTest.class;
- Field field = clazz.getDeclaredField("param");
- GenericArrayType arrayType = (GenericArrayType)field.getGenericType();
- TypeVariable variable = (TypeVariable) arrayType.getGenericComponentType();
- }
- }

我們在微信上24小時(shí)期待你的聲音
解答本文疑問/技術(shù)咨詢/運(yùn)營咨詢/技術(shù)建議/互聯(lián)網(wǎng)交流