1. 程式人生 > >Java泛型原理

Java泛型原理

最近一個東西困惑我: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。(可能還會自動進行一些轉型)