詳解Java類型擦除機(jī)制
Java泛型是JDK 5引入的一個特性,它允許我們定義類和接口的時候使用參數(shù)類型,泛型在集合框架中被廣泛使用。類型擦除是泛型中最讓人困惑的部分,本篇文章將闡明什么是類型擦除,以及如何使用它。
一個常見錯誤
package simplejava;
import java.util.ArrayList;
public class Q29 {
public static void main(String[] args) {
ArrayList<String> al = new ArrayList<String>();
al.add("a");
al.add("b");
accept(al);
}
public static void accept(ArrayList<Object> al) {
for (Object o : al)
System.out.println(o);
}
}
以上代碼看起來是沒問題的,因為String是Object的子類。然而,這并不會工作,編譯不會通過,并提示如下錯誤:
The method accept(ArrayList<Object>) in the type Q29 is not applicable for the arguments (ArrayList<String>)
List<Object>和List<String>
原因在于類型擦除。記?。篔ava的泛型機(jī)制是在編譯級別實現(xiàn)的。編譯器生成的字節(jié)碼在運(yùn)行期間并不包含泛型的類型信息。
在編譯之后,List<Object>和List<String>將變成List,Object和String類型信息對于JVM來說是不可見的。在編譯階段,編譯器發(fā)現(xiàn)它們不一致,因此給出了一個編譯錯誤。
通配符和有界通配符
List<? >表示List能包含任何類型的元素
public static void main(String args[]) {
ArrayList<Object> al = new ArrayList<Object>();
al.add("abc");
test(al);
}
public static void test(ArrayList<?> al) {
for (Object e : al) {// no matter what type, it will be Object
System.out.println(e);
// in this method, because we don't know what type ? is, we can not
// add anything to al.
}
}
永遠(yuǎn)記住,泛型是一個編譯時的概念。在這個例子中,由于我們不知道?,我們不能添加任何元素到al集合。如果想要添加的話,可以使用通配符。
List< Object > - List can contain Object or it's subtype
List< ? extends Number > - List can contain Number or its subtypes.
List< ? super Number > - List can contain Number or its supertypes.
與數(shù)組比較
現(xiàn)在,我們知道了ArrayList <String >并不是ArrayList <Object >的子類型,不過,你需要知道如果兩個泛型類型有相同的參數(shù),它們的繼承關(guān)系是依據(jù)其類型。如ArrayList<String>是Collecton<String>的子類型。
然而,數(shù)組卻不同,它們在運(yùn)行期間知道每個元素的類型且強(qiáng)制它們的元素為該類型,這叫reification。舉個例子,Object[] objArray是String[] strArr的超類型。如果你嘗試往存儲整型的數(shù)組添加字符串對象,將會在運(yùn)行期間得到一個ArrayStoreException異常。
譯文鏈接:http://www.programcreek.com/2011/12/java-type-erasure-mechanism-example/
總結(jié)
以上所述是小編給大家介紹的Java類型擦除機(jī)制,希望對大家有所幫助,如果大家有任何疑問歡迎給我留言,小編會及時回復(fù)大家的!
相關(guān)文章
springboot?整合?clickhouse的實現(xiàn)示例
本文主要介紹了springboot?整合?clickhouse的實現(xiàn)示例,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-02-02
Java中Lambda表達(dá)式和函數(shù)式接口的使用和特性
Java Lambda表達(dá)式是一種函數(shù)式編程的特性,可簡化匿名內(nèi)部類的寫法,與函數(shù)式接口搭配使用,實現(xiàn)代碼簡潔、可讀性高、易于維護(hù)的特點(diǎn),適用于集合操作、多線程編程等場景2023-04-04
JavaWeb?Servlet技術(shù)及其應(yīng)用實踐
這篇文章主要介紹了JavaWeb?Servlet技術(shù),Servlet指在服務(wù)器端執(zhí)行的一段Java代碼,可以接收用戶的請求和返回給用戶響應(yīng)結(jié)果,感興趣想要詳細(xì)了解可以參考下文2023-05-05
mall整合SpringTask實現(xiàn)定時任務(wù)的方法示例
這篇文章主要介紹了mall整合SpringTask實現(xiàn)定時任務(wù)的方法示例,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2019-06-06
java 實現(xiàn)單鏈表逆轉(zhuǎn)詳解及實例代碼
這篇文章主要介紹了java 實現(xiàn)單鏈表逆轉(zhuǎn)實例代碼的相關(guān)資料,需要的朋友可以參考下2017-02-02
IntelliJ IDEA 2021.1 EAP 1 發(fā)布支持 Java 16 和 WSL 2
這篇文章主要介紹了IntelliJ IDEA 2021.1 EAP 1 發(fā)布支持 Java 16 和 WSL 2,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-02-02
springboot+thymeleaf 文件上傳功能的實現(xiàn)代碼
這篇文章主要介紹了springboot+thymeleaf 文件上傳功能的實現(xiàn)代碼,代碼簡單易懂,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-11-11
啟用springboot security后登錄web頁面需要用戶名和密碼的解決方法
這篇文章主要介紹了啟用springboot security后登錄web頁面需要用戶名和密碼的解決方法,也就是使用默認(rèn)用戶和密碼登錄的操作方法,本文結(jié)合實例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下2023-02-02
詳解Spring MVC攔截器實現(xiàn)session控制
這篇文章主要介紹了詳解Spring MVC攔截器實現(xiàn)session控制,使用session監(jiān)聽,重復(fù)登錄后,強(qiáng)制之前登錄的session過期。有興趣的可以了解一下。2017-01-01

