<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                熟悉Java的同學應該會經常聽到Java的一大特性,就是向后兼容。簡單來說,就是老版本的Java文件編譯后可以運行在新版本的JVM上。我們知道,Java一開始是沒有泛型的,那么在Java 1.5之前,在程序中會出現大量的以下代碼: ``` ArrayList list = new ArrayList(); //沒有泛型 ``` 一般在沒有泛型的語言上支持泛型,一般有兩種方式,以集合為例: * 全新設計一個集合框架(全新實現現有的集合類或者創造新的集合類),不保證兼容老的代碼,優點是不需要考慮兼容老的代碼,寫出更符合新標準的代碼;缺點是需要適應新的語法,更嚴重的是可能無法改造老的業務代碼。 * 在老的集合框架上改造,添加一些特性,兼容老代碼的前提下,支持泛型。 很明顯,Java選擇了后種方式實現泛型,這也是有歷史原因的,主要有以下兩點原因: 1)在Java1.5之前已經有大量的非泛型代碼存在了,若不兼容它們,則會讓使用者抗拒升級,因為他要付出大量的時間去改造老代碼; 2)Java曾經有過重新設計一個集合框架的教訓,比如Java 1.1到Java1.2過程中的Vector到ArrayList, HashTable到HashMap,引起了大量使用者的不滿。 所以,Java為了填補自己埋下的坑,只能用一種比較別扭的方式實現泛型,那便是類型擦除。 那么,為什么使用類型擦除實現泛型可以解決我們上面說的新老代碼兼容的問題呢?我們先來看一下下面兩行代碼編譯后的內容: ``` ArrayList list = new ArrayList(); //(1) ArrayList<String> stringList = new ArrayList<String>(); //(2) ``` 對應字節碼: 0: new #2 // class java/util/ArrayList 3: dup 4: invokespecial #3 // Method java/util/ArrayList."<init>":()V 7: astore_1 8: new #2 // class java/util/ArrayList 11: dup 12: invokespecial #3 // Method java/util/ArrayList."<init>":()V 15: astore_2 我們發現**方式1和方式2聲明的ArrayList再編譯后的字節碼是完全一樣的**,這也說明了低版本編譯的class文件在高版本的JVM上運行不會出現問題。既然泛型在編譯后是會擦除泛型類型的,那么我們又為什么可以使用泛型的相關特性,比如類型檢查、類型自動轉換呢? **類型檢查是編譯器在編譯前就會幫我們進行類型檢查,所以類型擦除不會影響它**。那么類型自動轉換又是怎么實現的呢?我們來看一個例子: ``` ArrayList<String> stringList = new ArrayList<String>(); String s = stringList.get(0); ``` 這段代碼大家都應該很熟悉,get方法返回的值的類型就是List泛型參數的類型。來看一下ArrayList的get方法的源碼: @SuppressWarnings("unchecked") E elementData(int index) { return (E) elementData[index]; //強制類型轉換 } public E get(int index) { rangeCheck(index); return elementData(index); } 我們發現,背后也是通過強制類型轉化來實現的。這點從編譯后的字節碼也可以得到驗證: 0: new #2 // class java/util/ArrayList 3: dup 4: invokespecial #3 // Method java/util/ArrayList."<init>":()V 7: astore_1 8: aload_1 9: iconst_0 10: invokevirtual #4 // Method java/util/ArrayList.get:(I)Ljava/lang/Object; 獲取的是Object 13: checkcast #5 // class java/lang/String強制類型轉換 16: astore_2 17: return 所以可以得出結論,**雖然Java受限于向后兼容的困擾,使用了類型擦除來實現了泛型,但它還是通過其他方式來保證了泛型的相關特性**。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看