Java?泛型考古?泛型擦除?包裝類詳細解析
一. 什么是泛型
泛型(generic type)其本質是將類型參數(shù)化,也就是說所操作的數(shù)據類型被指定為一個參數(shù)這種參數(shù)類型可以用在類、接口和方法的創(chuàng)建中,分別稱為泛型類、泛型接口、泛型方法。
二. 為什么要有泛型 ?
之前寫過MyArrayList順序表,這個類當時自己在實現(xiàn)的時候只能用一種類型來表示,也就是用的時候自己實現(xiàn)的MyArrayList只能應用于一種類型,要想應用于其他類型,就得再寫一個其他類型的MyArrayList,這樣就比較麻煩,而有了泛型之后就很好的解決了這個問題,讓類型參數(shù)化,使得自己寫的MyArrayList可以適用于多種場景
通過以下代碼對比就可發(fā)現(xiàn)泛型的方便之處
示例
不帶泛型
public class MyArrayList {
private int[] array;
private int size; // 有效數(shù)據個數(shù)
public MyArrayList() {
this.array = new int[10];
this.size = 0;
}
public void add(int x) { // 暫不考慮擴容
this.array[size] = x;
this.size++;
}
}帶泛型
import org.omg.CORBA.Object;
public class MyArrayList2<E> {
// 在類的實現(xiàn)中,可以直接將類當成一種數(shù)據類型來使用。在實例化該類的時候這個類型才被確定
private E[] array;
private int size; // 有效數(shù)據個數(shù)
public MyArrayList2() {
this.array = (E[])new Object[10]; // 注意:Java中泛型不允許定義數(shù)組
this.size = 0;
}
public void add(E e) { // 不考慮擴容
this.array[size] = e;
this.size++;
}
}
// 帶泛型的順序表元素類型是一個“變量”
// E就是變量的名稱通過上面這兩段代碼的對比,就可以發(fā)現(xiàn),帶泛型的順序表和不帶泛型的順序表只是表示類型的部分不一樣,代碼所實現(xiàn)的邏輯是一樣的
類的實例化與使用
public static void main(String[] args) {
MyArrayList myArrayList = new MyArrayList();
myArrayList.add(1);
myArrayList.add(2);
// 這里其實就相當于是將String類型賦值給E
MyArrayList2<String> stringMyArrayList2 = new MyArrayList2<String>(); // 等號右邊的<>內可以省略
stringMyArrayList2.add("1"); // 要想用基本類型,要寫基本類型對應的包裝類
stringMyArrayList2.add("2");
}對于泛型來說,類型是在使用該類時才明確定義出來的
三、泛型考古
要知道其實剛開始Java體系中是沒有泛型的,是在JDK1.5之后才才有了泛型
在JDK1.5之前是利用Object引用可以指向任意類型的對象實現(xiàn)類似泛型的效果
- Object類是所有類的祖先類
- 上層引用可以指向下層對象
如下代碼:
public class MyArrayList3 {
private Object[] array;
private int size;
public MyArrayList3() {
this.array = new Object[10];
this.size = 0;
}
public void add(Object e) {
this.array[size] = e;
size++;
}
}這種做法的缺點也很明顯,就是new了一個MyArrayList,里面打算存int類型的數(shù)據,但由于手滑,存入了一個String類型的數(shù)據,這樣的話編譯器是不會報錯的,程序也能正常運行,直到需要取list中的元素的時候程序才會拋出異常。
泛型就很好的解決了這個問題,只要類型不匹配,錯誤會在第一時間暴露出來
四、泛型擦除
雖然在 JDK1.5 之后有了泛型,但其實JDK的底層實現(xiàn)還是用的上面Object來實現(xiàn)的
如下圖
![[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-sB60DwZz-1646265098596)(C:\Users\LY\AppData\Roaming\Typora\typora-user-images\image-20211210185132787.jpg)]](http://img.jbzj.com/file_images/article/202203/2022032310083143.jpg)
我們雖然用的是泛型,但其實泛型只存在于編譯階段,在編譯過程中也伴隨著泛型擦除,在生成.class文件的時候泛型信息就已經不存在了,成了JDK1.5之前的Object方式
查看MyArrayList的字節(jié)碼文件就可以看出來
![[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-KCvl7iYr-1646265098598)(C:\Users\LY\AppData\Roaming\Typora\typora-user-images\image-20220123202400988.jpg)]](http://img.jbzj.com/file_images/article/202203/2022032310083144.jpg)
所以Java的泛型只存在于編譯階段(Java核心原理:Object引用可以指向任意類型的對象)
五、包裝類
由于8種基本類型不是類類型,Java專門為它們定義了各自的包裝類
如下:
byte java.lang.Byte
short java.lang.Short
char java.lang.Character
int java.lang.Integer
long java.lang.Long
float java.lang.Float
double java.lang.Double
boolean java.lang.Boolean
六、裝箱拆箱
![[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-dsPrxxd0-1646265098599)(C:\Users\LY\AppData\Roaming\Typora\typora-user-images\image-20220212173816723.jpg)]](http://img.jbzj.com/file_images/article/202203/2022032310083145.jpg)
Java中提供了便利,如果沒有歧義,Java 會幫我們自動裝箱,自動拆箱
Integer a = 10; // 把int賦值給Integer類型,隱含著發(fā)生了裝箱過程 int b = a; // 把Integer賦值給int類型,隱含著發(fā)生了拆箱過程
隱式裝箱和拆箱過程只存在于編譯階段,編譯完成就變成顯式裝箱,顯式拆箱了
到此這篇關于Java 泛型考古 泛型擦除 包裝類詳細解析的文章就介紹到這了,更多相關Java 泛型 內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
詳解SpringBoot如何實現(xiàn)多環(huán)境配置
在實際的軟件開發(fā)過程中,一個應用程序通常會有多個環(huán)境,pring?Boot?提供了一個非常靈活和強大的方式來管理這些環(huán)境配置,下面就跟隨小編一起學習一下吧2023-07-07
編碼實現(xiàn)從無序鏈表中移除重復項(C和JAVA實例)
如果不能使用臨時緩存,你怎么實現(xiàn)無序鏈表中移除重復項(?C和JAVA實例無序鏈表中移除重復項。2013-10-10

