背景:泛型這個知識點平時用的很少,可是在面試的時候很容就被問到,因此仍是要準備一些基礎的知識儲備。java
「泛型」 意味着編寫的代碼能夠被不一樣類型的對象所重用。編程
泛型是在JDK1.5以後出現的。數組
泛型的本質是參數化類型,也就是說所操做的數據類型被指定爲一個參數。安全
能夠看到,使用 Object 來實現通用、不一樣類型的處理,有這麼兩個缺點:性能
根據《Java 編程思想》中的描述,泛型出現的動機在於:spa
有許多緣由促成了泛型的出現,而最引人注意的一個緣由,就是爲了建立容器類。.net
實際上引入泛型的主要目標有如下幾點:翻譯
泛型類 code
泛型接口
泛型方法
無限制通配符
extends 關鍵字聲明瞭類型的上界,表示參數化的類型多是所指定的類型,或者是此類型的子類
super 關鍵字聲明瞭類型的下界,表示參數化的類型多是指定的類型,或者是此類型的父類
經過上面的例子咱們能夠知道,無限制通配符 < ?> 和 Object 有些類似,用於表示無限制或者不肯定範圍的場景。
兩種有限制通配形式 < ? super E> 和 < ? extends E> 也比較容易混淆,咱們再來比較下。
ps:上下限用圖說明
它們的目的都是爲了使方法接口更爲靈活,能夠接受更爲普遍的類型。
用《Effective Java》 中的一個短語來加深理解:
爲了得到最大限度的靈活性,要在表示 生產者或者消費者 的輸入參數上使用通配符,使用的規則就是:生產者有上限、消費者有下限:
PECS: producer-extends, costumer-super
所以使用通配符的基本原則:
小總結一下:
Java 中的泛型和 C++ 中的模板有一個很大的不一樣:
(摘自:blog.csdn.net/fw0124/arti…)
在 Java 中,泛型是 Java 編譯器的概念,用泛型編寫的 Java 程序和普通的 Java 程序基本相同,只是多了一些參數化的類型同時少了一些類型轉換。
實際上泛型程序也是首先被轉化成通常的、不帶泛型的 Java 程序後再進行處理的,編譯器自動完成了從 Generic Java 到普通 Java 的翻譯,Java 虛擬機運行時對泛型基本一無所知。
當編譯器對帶有泛型的java代碼進行編譯時,它會去執行類型檢查和類型推斷,而後生成普通的不帶泛型的字節碼,這種普通的字節碼能夠被通常的 Java 虛擬機接收並執行,這在就叫作 類型擦除(type erasure)。
當類中要操做的引用數據類型不肯定的時候,過去使用 Object 來完成擴展,JDK 1.5後推薦使用泛型來完成擴展,同時保證安全性。
1.上面說到使用 Object 來達到複用,會失去泛型在安全性和直觀表達性上的優點,那爲何 ArrayList 等源碼中的還能看到使用 Object 做爲類型?
根據《Effective Java》中所述,這裏涉及到一個 「移植兼容性」:
泛型出現時,Java 平臺即將進入它的第二個十年,在此以前已經存在了大量沒有使用泛型的 Java 代碼。人們認爲讓這些代碼所有保持合法,而且可以與使用泛型的新代碼互用,很是重要。
這樣都是爲了兼容,新代碼裏要使用泛型而不是原始類型。
2.泛型是經過擦除來實現的。所以泛型只在編譯時強化它的類型信息,而在運行時丟棄(或者擦除)它的元素類型信息。擦除使得使用泛型的代碼能夠和沒有使用泛型的代碼隨意互用。
3.若是類型參數在方法聲明中只出現一次,能夠用通配符代替它。
好比下面的 swap 方法,用於交換指定 List 中的兩個位置的元素:
private void swap(List list, int i, int j) { //... }
只出現了一次 類型參數,沒有必要聲明,徹底能夠用通配符代替:
private void swap(List list, int i, int j){ //... }
對比一下,第二種更加簡單清晰吧。
4.數組中不能使用泛型
這多是 Java 泛型面試題中最簡單的一個了,固然前提是你要知道 Array 事實上並不支持泛型,這也是爲何 Joshua Bloch 在 《Effective Java》一書中建議使用 List 來代替 Array,由於 List 能夠提供編譯期的類型安全保證,而 Array 卻不能。
5.Java 中 List
和原始類型 List
之間的區別?
原始類型和帶參數類型 之間的主要區別是:
這道題的考察點在於對泛型中原始類型的正確理解。
ps:這個地方還沒理解。。。。