詳解Java類型擦除機(jī)制
Java泛型是JDK 5引入的一個(gè)特性,它允許我們定義類和接口的時(shí)候使用參數(shù)類型,泛型在集合框架中被廣泛使用。類型擦除是泛型中最讓人困惑的部分,本篇文章將闡明什么是類型擦除,以及如何使用它。
一個(gè)常見錯(cuò)誤
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); } }
以上代碼看起來是沒問題的,因?yàn)镾tring是Object的子類。然而,這并不會工作,編譯不會通過,并提示如下錯(cuò)誤:
The method accept(ArrayList<Object>) in the type Q29 is not applicable for the arguments (ArrayList<String>)
List<Object>和List<String>
原因在于類型擦除。記住:Java的泛型機(jī)制是在編譯級別實(shí)現(xiàn)的。編譯器生成的字節(jié)碼在運(yùn)行期間并不包含泛型的類型信息。
在編譯之后,List<Object>和List<String>將變成List,Object和String類型信息對于JVM來說是不可見的。在編譯階段,編譯器發(fā)現(xiàn)它們不一致,因此給出了一個(gè)編譯錯(cuò)誤。
通配符和有界通配符
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)記住,泛型是一個(gè)編譯時(shí)的概念。在這個(gè)例子中,由于我們不知道?,我們不能添加任何元素到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 >的子類型,不過,你需要知道如果兩個(gè)泛型類型有相同的參數(shù),它們的繼承關(guān)系是依據(jù)其類型。如ArrayList<String>是Collecton<String>的子類型。
然而,數(shù)組卻不同,它們在運(yùn)行期間知道每個(gè)元素的類型且強(qiáng)制它們的元素為該類型,這叫reification。舉個(gè)例子,Object[] objArray是String[] strArr的超類型。如果你嘗試往存儲整型的數(shù)組添加字符串對象,將會在運(yùn)行期間得到一個(gè)ArrayStoreException異常。
譯文鏈接:http://www.programcreek.com/2011/12/java-type-erasure-mechanism-example/
總結(jié)
以上所述是小編給大家介紹的Java類型擦除機(jī)制,希望對大家有所幫助,如果大家有任何疑問歡迎給我留言,小編會及時(shí)回復(fù)大家的!
相關(guān)文章
使用idea的database模塊繪制數(shù)據(jù)庫er圖的方法
這篇文章主要介紹了使用idea的database模塊繪制數(shù)據(jù)庫er圖,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-07-07Jackson中json格式的字符串與對象的互相轉(zhuǎn)換方式
這篇文章主要介紹了Jackson中json格式的字符串與對象的互相轉(zhuǎn)換方式,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-07-07@ConfigurationProperties綁定配置信息至Array、List、Map、Bean的實(shí)現(xiàn)
這篇文章主要介紹了@ConfigurationProperties綁定配置信息至Array、List、Map、Bean的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-05-05Java中使用DOM4J生成xml文件并解析xml文件的操作
這篇文章主要介紹了Java中使用DOM4J來生成xml文件和解析xml文件的操作,今天通過代碼給大家展示了解析xml文件和生成xml文件的方法,需要的朋友可以參考下2021-09-09Java實(shí)現(xiàn)多線程大批量同步數(shù)據(jù)(分頁)
這篇文章主要為大家詳細(xì)介紹了Java實(shí)現(xiàn)多線程大批量同步數(shù)據(jù)(分頁),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-08-08Java Scanner對象中hasNext()與next()方法的使用
這篇文章主要介紹了Java Scanner對象中hasNext()與next()方法的使用,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-10-10Java 線程池_動力節(jié)點(diǎn)Java學(xué)院整理
系統(tǒng)啟動一個(gè)新線程的成本是比較高的,因?yàn)樗婕暗脚c操作系統(tǒng)的交互。在這種情況下,使用線程池可以很好的提供性能,尤其是當(dāng)程序中需要創(chuàng)建大量生存期很短暫的線程時(shí),更應(yīng)該考慮使用線程池2017-05-05