什麼,JAVA的泛型是偽泛型

2021-01-16 3號拖鞋

泛型是JDK 1.5的一項新增特性,它的本質是參數化類型(ParametersizedType)的應用,也就是說所操作的數據類型被指定為一個參數(是不是像lambda表達式差不多的用義,用函數作為一個方法的參數)。這種參數類型可以用在類、接口和方法的創建中,分別稱為泛型類、泛型接口和泛型方法。

具體來說,我們先通過對比下代碼,來進一步體會泛型的好處

先看看沒有支持泛型之前的代碼

沒有運用泛型的代碼
運用泛型的代碼示範

由以上兩個例子可以看出:

引入泛型後,代碼在前端編譯的時候會做檢查,不會像1.5的代碼示範一樣,直到程序運行期才提示異常。通過現代idea自動編譯功能,由此可以大大提高我們的編程效率

但是有關java的泛型有一些值得思考的問題:

方法重載
編譯異常

代碼示範:用兩個不同List類型參數重載getName方法編譯報錯,why?

以上現象是因為在編譯時泛型擦除造成的,什麼? 泛型擦除又是什麼鬼?

我們可以通過字節碼來分析這個問題

代碼示範
字節碼片段

然後用jd-gui工具反編譯回java代碼

反編譯後的代碼

通過對比可以看出,反編譯的代碼跟我們之前寫的代碼不一致了,代碼風格也用回1.5之前的強制類型轉換了,即高版本支持某些語法糖的編程風格編譯之後轉化為低版本代碼風格了(解語法糖)

現在我們可以知道為什麼用兩個不同List類型參數重載getName方法會編譯報錯了:

兩個不同List類型參數,在編譯的時候都轉為List<Object>了,然後就不符合重載的定義了

所以有個哲學上的問題:

List<Integer>

List<String>

其實這兩個類型不是真正意義上的類型,他們在某種意義上還是一個List類型,只是套了層修飾,這種表面上的修飾作用很有利於編程人員,過了編譯期,這種修飾就沒有意義了,當然,為了運行期反射來獲取這種修飾符號,在編譯成字節碼時,增加了一些屬性來記錄這個具體的類型,解決伴隨泛型而來的參數類型的識別問題,如如Signature、LocalVariableTypeTable

Signature和LocalVar

所以有個說法是:java實現的泛型,其實不是真正意義上的泛型,是偽泛型

相關焦點

  • Java泛型了解麼?什麼是類型擦除?介紹一下常用的通配符?
    Java 泛型(generics)是 JDK 5 中引入的一個新特性, 泛型提供了編譯時類型安全檢測機制,該機制允許程式設計師在編譯時檢測到非法的類型。泛型的本質是參數化類型,也就是說所操作的數據類型被指定為一個參數。
  • Java基礎學習,什麼是泛型概念,使用泛型有哪些好處?
    泛型的字面概念:適合用於許多類型。在面向對象中,多態算是一種泛化機制。泛型的使用例子:在如圖的例子中T就是類型參數當你創建Holder對象時,必須指明想持有什麼類型的對象,將其置於尖括號內,就像main()中那樣。然後,你就只能在Holder中存入該類型(或其子類,以為多態與泛型不衝突)的對象了。
  • 高頻考點:什麼是泛型,泛型的使用場景
    一起學習、成長、溫情的熱愛生活作者丨BossXiang 圖丨pexels泛型的使用場景,可以作用在什麼位置,使用泛型有什麼好處,靈魂三連問???1.泛型就是一種未知的類,將未知的類型聲明在集合、對象上,泛型的默認類型為Object。
  • Java泛型的約束與局限性
    運行時類型查詢只適用於原始類型(raw type)運行時:通常指在Classloader裝載之後,JVM執行之時類型查詢:instanceof、getClass、強制類型轉換原始類型:即(raw type),泛型類型經編譯器類型擦除後是Object或泛型參數的限定類型(例如Pair,Comparable就是T的限定類型,轉化後泛型的原始類型就是
  • 一句話概述什麼是泛型,教你直白理解Java泛型
    泛型就是把類型明確的工作推遲到創建對象或調用方法的時候採取明確的特殊類型。參數化類型:把類型當做參數來傳遞。Object<數據類型>,這裡的數據類型只能是類類型,不能是基本類型。為什麼不能是基本類型?
  • 如何通俗易懂地理解什麼叫泛型?
    如何理解泛型?作文題材不限,記敘文、議論文、詩歌都可以。但是不能一篇作文既寫成記敘文又寫成議論文。一旦你確定了題材(比如說寫議論文),那麼這篇作文就不能寫其他題材了(只能寫議論文)想寫其他題材,那下一篇作文重新寫。所以什麼叫泛型?就好比作文題材不限,但一次只能寫一種題材,至於是什麼題材,由我們自己定。
  • 快報:正式提案將泛型特性加入 Go 語言
    快報:正式提案將泛型特性加入 Go 語言 經歷九九八十一難,多年的不斷探討和 Go 語言愛好者們在社區中的強烈關注,且 Go 官方在 2020 年不斷放出消息。
  • 大佬|從啥也不會,到Java大佬,他就因為會了這一門絕技
    從一個啥也不會的Java小白,到Java大佬,就因為會了這一門杜門絕跡,泛型,成為令人仰慕的大佬,今天是本周的第六篇,主要內容是Java泛型什麼是泛型例如一段代碼//創建一個List集合ArrayList al = new ArrayList();al.add(123); //添加基本數據類型對象al.add("123"); //添加String對象al.add
  • Go 擺脫了 C,又惹上了 Java?
    nil 引用,運行時邊界檢查)變量總是初始化 (zero/nil/false)方法接口類型斷言 (實例)反射Go 與 Java 的不同之處代碼程序直接編譯成機器碼,沒有 VM靜態連結二進位內存布局控制函數值和詞法閉包內置字符串 (UTF-8)內置泛型映射和數組
  • Go語言和Java、Python等其他語言的對比分析
    Go 語言的語法特性簡直是太簡單了,簡單到你幾乎玩不出什麼花招,直來直去的,學習曲線很低,上手非常快。2、效率:快速的編譯時間,開發效率和運行效率高開發過程中相較於 Java 和 C++呆滯的編譯速度,Go 的快速編譯時間是一個主要的效率優勢。Go擁有接近C的運行效率和接近PHP的開發效率。
  • 北大青鳥學士後Java課程體系
    3、流程控制言基礎4、數組5、課程項目訓練1、類和對象1、掌握面向對象編程技術Java 面向對2、繼承和多態2、能夠使用面向對象編程思想3、抽象類和接口編寫程序象程序設計4、異常5、綜合練習1、集合框架和泛型
  • 北大青鳥:學士後Java軟體工程師的主要課程有哪些?
    武漢北大青鳥中南軟體學院Java軟體工程師(6.0)課程內容:01、掌握Java語言的使用語言語法、程序邏輯OOP(面向對象)思想,封裝、繼承、多態集合框架、泛型、FileI\O
  • 跟我學java編程—Java條件運算符
    在D盤Java目錄下,新建「TaxSample.java」文件。用記事本打開「TaxSample.java」文件,輸入以下代碼:代碼結構分析程序功能主要是演示條件運算符的使用。編譯「TaxSample.java」文件,在命令行窗口輸入「javac TaxSample.java」並執行命令,編譯通過後,在命令行窗口輸入「java TaxSample」運行Java程序,命令行窗口顯示如下信息:
  • Go+iris吊打Java+SpringBoot,是Java老了嗎?且慢,Vert.x有話說
    Go+Iris vs Java+SpringBoot 為您揭曉答案那個結果很容易給人一個錯覺:是java老了嗎?當然不是!Java界的性能擔當根本就不是Spring,只是因為國內用java的web框架主要是Spring,我們才拿它來測……本次我們就請出java界的性能擔當——Vert.x,跟Iris再比一次這次的結果會比較有說服力因為iris在官網自稱自己是 the fastest web framework,請注意:它並沒有加任何修飾詞,比如go語言中最快的,而是直說是最快的
  • 在被瘋狂嘲諷之後,我決定研究下Java中的過濾器源碼
    ③ArrayList<File> files = new ArrayList<>();創建一個ArrayList集合files,泛型為File,也就是說files這個集合只能用來存儲File對象。
  • JAVA專業術語面試100問
    2、接口和抽象類有什麼聯繫和區別?3、重載和重寫有什麼區別?4、java有哪些基本數據類型?5、數組有沒有length()方法?String有沒有length()方法?Error與Exception有什麼區別?17、java中的throw 和 throws關鍵字有什麼區別?18、列舉幾個你了解的幾個常見的運行時異常?19、final, finally, finalize有什麼區別?