今天我們不講泛型的來龍去脈栖雾,講講泛型到底有哪些類別,也就是Type
這個接口到底有多少不同的實現(xiàn)(jdk中)
大家可能會疑惑,泛型還能有多種不同的類型村怪?
這不是我前段時間寫了一個庫【Java】簡單優(yōu)雅的加載外部 jar 中的 Class|插件化
在這個庫中我需要實現(xiàn)一個功能:通過泛型來推導(dǎo)數(shù)據(jù)類型來加載對應(yīng)的插件內(nèi)容
于是我就對我們平時常用的泛型做了一些研究
如果大家之前有去了解過相關(guān)的內(nèi)容,就會知道Type
接口會有一些不同的實現(xiàn)(jdk中)
Class
TypeVariable
ParameterizedType
WildcardType
GenericArrayType
那么今天我們就來看看這些類型都對應(yīng)了什么寫法的泛型
Class
首先Class
我們接觸的比較多浮庐,雖然實現(xiàn)了Type
接口甚负,但不是泛型,就是普通的類的類型审残,并不具有泛型的一些參數(shù)屬性
TypeVariable
可變類型梭域,可以得到最原始的類型信息
如我們常用的ArrayList<E>
我們可以通過getTypeParameters
來獲得他的泛型信息
ArrayList.class.getTypeParameters();
但是我們只能拿到E
,拿不到具體的類型搅轿,畢竟實例化之后任意的類型都有可能
那么有沒有能拿到具體類型的泛型呢病涨,我們繼續(xù)往下看
ParameterizedType
參數(shù)化類型,可以獲得<
>
中定義的具體類型
假設(shè)我們繼承ArrayList
并指定泛型為String
public class StringArrayList extends ArrayList<String> {
}
這種情況下璧坟,我們就可以使用getGenericSuperclass
來獲得泛型信息
StringArrayList.class.getGenericSuperclass();
調(diào)用上面的方法我們就能得到一個ParameterizedType
通過ParameterizedType#getRawType()
就可以獲得ArrayList.class
通過ParameterizedType#getActualTypeArguments()
就可以獲得String.class
ParameterizedType type = (ParameterizedType) StringArrayList.class.getGenericSuperclass();
Type rawType = type.getRawType();
System.out.println(rawType);
//輸出 class java.util.ArrayList
Type actualTypeArgument = type.getActualTypeArguments()[0];
System.out.println(actualTypeArgument);
//輸出 class java.lang.String
WildcardType
通配符類型既穆,可以獲得泛型的類型界限
主要通過? extends
或? super
約束
舉個例子
public class ClassArrayList extends ArrayList<Class<? extends Serializable>> {
}
其中? extends Serializable
就是WildcardType
這里需要注意的是不帶<
>
通過WildcardType#getUpperBounds()
就可以獲得Serializable.class
ParameterizedType type = (ParameterizedType) ClassArrayList.class.getGenericSuperclass();
Type rawType = type.getRawType();
System.out.println(rawType);
//輸出 class java.util.ArrayList
ParameterizedType actualTypeArgument = (ParameterizedType) type.getActualTypeArguments()[0];
System.out.println(actualTypeArgument);
//輸出 java.lang.Class<? extends java.io.Serializable>
Type argumentRawType = actualTypeArgument.getRawType();
System.out.println(argumentRawType);
//輸出 class java.lang.Class
WildcardType argumentActualTypeArgument = (WildcardType) actualTypeArgument.getActualTypeArguments()[0];
System.out.println(argumentActualTypeArgument);
//輸出 ? extends java.io.Serializable
Type upperBound = argumentActualTypeArgument.getUpperBounds()[0];
System.out.println(upperBound);
//輸出 interface java.io.Serializable
GenericArrayType
泛型數(shù)組類型,表示泛型類型的數(shù)組類型
修改一下上面的例子
public class ClassesArrayList extends ArrayList<Class<? extends Serializable>[]> {
}
實際上就是在原本的泛型類型外又包了一層
ParameterizedType type = (ParameterizedType) ClassesArrayList.class.getGenericSuperclass();
Type rawType = type.getRawType();
System.out.println(rawType);
//輸出 class java.util.ArrayList
GenericArrayType actualTypeArgument = (GenericArrayType) type.getActualTypeArguments()[0];
System.out.println(actualTypeArgument);
//輸出 java.lang.Class<? extends java.io.Serializable>[]
ParameterizedType genericComponentType = (ParameterizedType) actualTypeArgument.getGenericComponentType();
System.out.println(genericComponentType);
//輸出 java.lang.Class<? extends java.io.Serializable>
Type argumentRawType = genericComponentType.getRawType();
System.out.println(argumentRawType);
//輸出 class java.lang.Class
WildcardType argumentActualTypeArgument = (WildcardType) genericComponentType.getActualTypeArguments()[0];
System.out.println(argumentActualTypeArgument);
//輸出 ? extends java.io.Serializable
Type upperBound = argumentActualTypeArgument.getUpperBounds()[0];
System.out.println(upperBound);
//輸出 interface java.io.Serializable
沒見過的泛型寫法
接下來再說一個我在查資料時見到的一種泛型寫法
public class Custom<T extends Serializable & Cloneable> {
}
不知道大家之前有沒有遇到過這樣的寫法
然后我就研究了一下雀鹃,發(fā)現(xiàn)這其實就是一個AND
條件
上面的接口表示幻工,這個泛型必須要實現(xiàn)Serializable
和Cloneable
,兩個都要滿足
所以比如ArrayList
就是可以的:Custom<ArrayList>
而且泛型中的條件可以有多個黎茎,但是最多只能有一個類囊颅,其他必須為接口
可以猜想是java
只能繼承一個父類但是可以實現(xiàn)多個接口的原因
那么今天的內(nèi)容就是這樣啦