Java泛型原理
阿新 • • 發佈:2019-01-30
最近一個東西困惑我:Java泛型,Lambda是否是編譯器行為?為什麼Java 若干版本以後就支援了呢?如果說在jdk1.5之前使用了泛型,還能使用嗎?
看一段介紹
Java泛型被引入的好處是安全簡單。 在Java SE 1.5之前,沒有泛型的情況的下,通過對型別Object的引用來實現引數的“任意化”,“任意化”帶來的缺點是要做顯式的強制型別轉換,而這種轉換是要求開發者對實際引數型別可以預知的情況下進行的。對於強制型別轉換錯誤的情況,編譯器可能不提示錯誤,在執行的時候才出現異常,這是一個安全隱患。 泛型的好處是在編譯的時候檢查型別安全,並且所有的強制轉換都是自動和隱式的,提高程式碼的重用率。
這段文字看完後,大概就明白了,又是語法糖的常用套路: 隱式替我們做一些事,這裡替我們做了隱式的強轉。
既然是編譯器行為,那麼為什麼和jdk有關?jdk在1.5之前,還可以使用泛型嗎?
我是 這樣理解的:假如在jdk1.5後,編譯器用了泛型,然後拿到位元組碼;放到jdk1.4的環境裡,依然是可以執行的。因為這是編譯器行為。編譯器在jdk1.5後,會遵守jdk規範,設定了一套支援泛型的解析機制。
所以型別擦除,就是編譯的時候把程式碼改成了,強轉。
為了更好地理解 型別擦除,舉個例子
private void test() { ArrayList<String> al = new ArrayList<String>(); al.add("a"); al.add("b"); accept(al); } public void accept(ArrayList<Object> al) { for (Object o : al) System.out.println(o); }
會報錯。
private void test() { accept("1"); } public void accept(Object al) { }
這樣是ok的。
原因:這裡確實String是Object的例項, String轉Object好轉,但是List<String>轉List<Object>就不好轉了。再看一個例子。
private void test() { accept((String) new Object()); } public void accept(String al) { }
只有 強轉過後,編譯器 覺得才ok。如果沒有 強轉,編譯器還是不ok。
所以編譯器不放心你,String到底是不是Object的子類,你必須把物件 強轉了,才放心。
說了半天,泛型是什麼 原理?編譯器行為, 底層自動認為泛型是Object。(可能還會自動進行一些轉型)