深入理解Java泛型的用法 征服Java面試

Java泛型

相信看到這篇文章的人都是來爲面試做準備的,這篇文章就帶你徹底征服面試官對Java泛型的考察。
我們首先帶着幾個問題去了解。

一.泛型是什麼,你爲什麼要使用泛型

1.泛型是java中的一種形式參數,可以理解爲Java的一個語法。
2.好處:
1).使用泛型能增加我們代碼的可重用性。
2).泛型能幫我們把一些錯誤提前在編譯期。例如ClassCastException,在編譯期間就會提示你類型轉換錯誤。
解釋:
爲什麼說泛型能幫我們把錯誤提前在編譯期呢?比如我們在某個類中用參數的類型Object替代泛型,那你在使用的時候就需要把
Object類型強轉爲我們賦值的類型。這樣就很有可能在運行時發生ClassCastException,如果我們使用泛型,那麼在編譯的時候
能直接使用你指定的類型。而不需要強轉。

**

二.Java泛型的原理?什麼是泛型擦除機制?

**
Q:Java編譯器具體是如何擦除泛型的
A:Java泛型是JDK1.5引入進來的特性,爲了向下兼容,虛擬機本身是不支持泛型的,所以Java實現的是一種僞泛型機制,也就是說Java在編譯期擦除了所有的泛型信息,這樣Java就不需要產生新的類型到字節碼,所有的泛型類型最終都是一種原始類型,在Java運行時根本就不存在泛型信息。
Q:Java編譯器具體是如何擦除泛型的
A:1.檢查泛型邊界,獲取目標類型
2. 擦除類型變量,並替換爲限定類型,如果泛型類型的類型變量沒有限定(),則 用Object作爲原始類型,如果有限定(),則用XClass作爲原始類型, 如果有多個限定(T extends XClass1&XClass2),則使用第一個邊界XClass1作爲原始類。
3. 在必要時插入類型轉換以保持類型安全。
4. 生成橋方法以在擴展時保持多態性。

三. 使用泛型以及泛型擦除帶來的影響(副作用)

Q: 1. 不能使用instanceof 運算符
A: 因爲擦除後,ArrayList只剩下原始類型,泛型信息String不存在了,所有沒 法使用instanceof。
Q: 2. 泛型在靜態方法和靜態類中的問題
A: 因爲泛型類中的泛型參數的實例化是在定義泛型類型對象
(比如ArrayList)的時候指定的,而靜態成員是不需要使用。
對象來調用的,所有對象都沒創建,如何確定這個泛型參數是什麼。
Q: 3. 泛型類型中的方法衝突
A: 因爲擦除後兩個equals方法變成一樣的了。
Q: 4. 沒法創建泛型實例
A: 因爲類型不確定
Q: 5 沒有泛型數組
A: 因爲數組是協變,擦除後就沒法滿足數組協變的原則

四.Pecs原則 限定原則

什麼叫Pecs原則
1.Producer Extend 代碼表示爲 List<? extend T>
那它代表什麼意思呢,它表示限定上屆爲T,該List裏面裝的都是T的子類。
看下面這段代碼,定義了一個copy方法,接受的是List<? extends B> 類型的參數,它表示接受的參數就是B的子類類型的list。那這個參數我們可傳入C類型的list,因爲C是B的子類。copy方法中只能對list進行get操作,爲什麼呢?因爲我們限定了該類型的上屆,裏面可以放任何B類型的子類,但我們不知道當前到底是放什麼子類的list,可以是C,也可能是繼承了B的D。如果讓你add元素,就可能導致發生運行時錯誤,所以就乾脆不讓你add。但是編譯器可以肯定的是get出來的元素一定是B。所以你是可以get出B類型的元素。

 public static void main(String[] args) {
        List<C> s3 = new ArrayList<>();
        copy(s3);
    }

    public static void copy(List<? extends B> list) {
       B b = list.get(0);
       list.add(new B());  //編譯錯誤
    }
    
class A {

}

class B extends A {

}

class C extends B {

}

2.Consumer Super 代碼表示爲List<? super T>
這個又代表什麼意思呢,它表示下屆爲T,該List裏面裝的都是T的父類。
看下面的段代碼,copy1方法接受B類型的所有父類參數。所有我們可以傳入A類型的List。
在copy方法中可以對list進行add操作,add可以是A的任何子類。你也可以get出來元素,但是你get出來的只能是Object類型的,因爲限定的是上屆,編譯器是不知道,add的到底是A的哪個子類,所以get出來只能是Objec類型。

    public static void main(String[] args) {
        List<A> s4 = new ArrayList<>();
        copy1(s4);
    }

    public static void copy1(List<? super B> list) {
       Object o  =  list.get(0);
       C c = new C();
       list.add(c);
    }


}

 class A {

}

class B extends A {

}

class C extends B {

}

如果你理解不了Pesc原則的話,就記住一句話,總結下就是上限只讀,下屆只添加。
關於面試的基本也就問這些了,再問就是C語言的東西了~~ 我也不會 哈哈哈

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章