故事背景
《互換身體》是由環球影業發行的喜劇電影,於2011年8月5日在美國上映。該片由大衛·道金執導,瑞安·雷諾茲、傑森·貝特曼、奧利維亞·王爾德等主演。該片講述了一位居家好男人和一位蜂蝶浪子分別厭倦了自己的生活,於是在某種神秘力量的輔助下兩人互換身體與生活的故事。

大話西游:紫霞和八戒互換了身體,欲和至尊寶親熱,結果直接吐了

java的換身術
java中也可以實現神奇的魔法,比如把String放入List<Integer>或者把Integer放入List<String>.請看:
public static void main(String[] args) { ArrayList<Integer> list = new ArrayList<Integer>(); list.add(1); list.add(2); list.add(3); try { list.getClass().getMethod("add", Object.class).invoke(list, "www"); } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException | SecurityException e) { e.printStackTrace(); } for (int i = 0; i < list.size(); i++) { System.out.println(list.get(i)); } }
打印出的結果為:
1
2
3
www

震驚了嗎? 整數的list里面竟然有字符串!!!
類型的限定是不是沒有其作用?不信的話,繼續看:
public static void main(String[] args) { ArrayList<Integer> ints = new ArrayList<Integer>(); ints.add(1); ints.add(2); ints.add(3); ArrayList<String> sts = new ArrayList<String>(); sts.add("a"); sts.add("b"); sts.add("c"); System.out.println(ints.getClass() == sts.getClass()); }
結果是什么呢?運行來看,結果為true

原來是類型擦除惹的禍。
類型擦除
當編譯器對帶有泛型的 Java 代碼進行編譯時,它會去執行類型檢查和類型推斷,然后生成普通的不帶泛型的字節碼,這種字節碼可以被一般的 Java 虛擬機接收並執行,這種技術被稱為擦除(erasure)。
因為種種原因,Java不能實現真正的泛型,只能使用類型擦除來實現偽泛型,這樣雖然不會有類型膨脹問題,但是也引起來許多新問題,所以,SUN對這些問題做出了種種限制,避免我們發生各種錯誤。
編譯器可以在對源程序(帶有泛型的 Java 代碼)進行編譯時使用泛型類型信息保證類型安全,對大量如果沒有泛型就不會去驗證的類型安全約束進行驗證,同時在生成的字節碼當中,將這些類型信息清除掉。
Java 中的泛型與 C++ 模板的比較
GJ(Generic Java)程序的語法在表面上與 C++ 中的模板非常類似,但是二者之間有着本質的區別。
首先,Java 語言中的泛型不能接受基本類型作為類型參數――它只能接受引用類型。這意味着可以定義 List<Integer>,但是不可以定義 List<int>。
其次,在 C++ 模板中,編譯器使用提供的類型參數來擴充模板,因此,為 List<A> 生成的 C++ 代碼不同於為 List<B> 生成的代碼,List<A> 和 List<B> 實際上是兩個不同的類。而 Java 中的泛型則以不同的方式實現,編譯器僅僅對這些類型參數進行擦除和替換。類型 ArrayList<Integer> 和 ArrayList<String> 的對象共享相同的類,並且只存在一個 ArrayList 類。
參考資料
【1】https://baike.baidu.com/item/%E4%BA%92%E6%8D%A2%E8%BA%AB%E4%BD%93/510590?fr=aladdin
【2】https://www.cnblogs.com/wuqinglong/p/9456193.html
【3】https://www.ibm.com/developerworks/cn/java/j-lo-gj/?mhsrc=ibmsearch_a&mhq=%E7%B1%BB%E5%9E%8B%E6%93%A6%E9%99%A4