java泛型
java泛型介紹
java泛型的參數(shù)只可以代表類(lèi)吴攒,不能代表個(gè)別對(duì)象。由于java泛型的類(lèi)型參數(shù)之實(shí)際類(lèi)型在編譯時(shí)會(huì)被消除砂蔽,所以無(wú)法在運(yùn)行時(shí)得知其類(lèi)型參數(shù)的類(lèi)型洼怔。java編譯器在編譯泛型時(shí)會(huì)自動(dòng)加入類(lèi)型轉(zhuǎn)換的編碼,故運(yùn)行速度不會(huì)因?yàn)槭褂梅盒投涌臁?/p>
泛型的好處是在編譯的時(shí)候檢查類(lèi)型安全左驾,并且所有的強(qiáng)制轉(zhuǎn)換都是自動(dòng)和隱式的茴厉,以提高代碼的復(fù)用率。
jvm泛型類(lèi)型擦除的規(guī)則:
- 若泛型沒(méi)有制定具體類(lèi)型什荣,用Object作為原始類(lèi)型。
- 若有限定類(lèi)型 <T extends XClass>,使用XClass作為原始類(lèi)型怀酷。
- 若有多個(gè)限定<T extends XClass1 & XClass2>,使用第一個(gè)邊界類(lèi)型XClass1作為原始類(lèi)型稻爬。
泛型中的 extends 和 super介紹
[圖片上傳失敗...(image-75c81e-1634181875986)]
[圖片上傳失敗...(image-fd137c-1634181875986)]
為什么要泛型擦除
我自己的思考是因?yàn)閖vm中的類(lèi)加載機(jī)制,虛擬機(jī)會(huì)把類(lèi)信息加載到j(luò)vm中的方法區(qū)蜕依, 前面已經(jīng)說(shuō)過(guò)采用泛型是為了更好的復(fù)用桅锄,現(xiàn)在我們想一個(gè)場(chǎng)景,如果我們把所有的泛型類(lèi)都加載到j(luò)vm中的方法區(qū)中區(qū)样眠,就會(huì)導(dǎo)致jvm中類(lèi)信息爆炸友瘤。例如List<Integer>, List<Integer>, List<X1>,List<X2> ... 。這些類(lèi)信息在虛擬機(jī)中統(tǒng)一只加載List.
例子如下:
public class GenericType <T>{
T value;
public GenericType(T value) {
this.value = value;
}
public void handleValue(){
System.out.println("handle value =>" + value.toString());
}
}
public static void main(String[] args) {
GenericType<String> gStr = new GenericType<>("i am a string object");
GenericType<Integer> gInteger = new GenericType<>(10000);
System.out.println(gStr.getClass().getName());
System.out.println(gInteger.getClass().getName());
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
while (classLoader != null) {
System.out.println("classLoader:" + classLoader);
try {
Vector<Class<?>> classes = ClassPrint.list(classLoader);
for (Class<?> c :
classes) {
System.out.println("\t" + c.getName());
}
classLoader = classLoader.getParent();
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
console中打印的信息如下:
com.df.qq.generic.GenericType
com.df.qq.generic.GenericType
classLoader:sun.misc.Launcher$AppClassLoader@18b4aac2
com.intellij.rt.execution.application.AppMainV2$Agent
com.intellij.rt.execution.application.AppMainV2
com.intellij.rt.execution.application.AppMainV2$1
com.df.qq.generic.GenericTest
com.df.qq.generic.GenericType
com.df.qq.generic.ClassPrint
classLoader:sun.misc.Launcher$ExtClassLoader@5e2de80c
Process finished with exit code 0