深入剖析Java泛型

首先,我們要從概念上認(rèn)識(shí)泛型,泛型的作用是什么?泛型是為了能夠在編譯時(shí)而不是在運(yùn)行時(shí)檢測(cè)出錯(cuò)誤而產(chǎn)生的,以提高程序的可靠性、健壯性和魯棒性。

有部分讀者可能會(huì)有這樣的理解誤區(qū):
如定義泛型ArrayList<String>list,比定義原始類型ArrayList list,能提高程序運(yùn)行的效率,能減少JVM底層識(shí)別數(shù)據(jù)類型的時(shí)間。
注意!不管實(shí)際的具體類型是什么,泛型類是被它的所有實(shí)例所共享的,在JVM中只有原始類型被存儲(chǔ)為單獨(dú)一個(gè)類

如下面的例子所示

ArrayList<String> list1 = new ArrayList<String>();
ArrayList<Integer> list2 = new ArrayList<Integer>();
System.out.println(list1 instanceof ArrayList);  //true
System.out.println(list2 instanceof ArrayList);  //true
System.out.println(list1 instanceof ArrayList<String>);  //false

由此可知,泛型存在于編譯時(shí),一旦編譯器確認(rèn)泛型類型是安全使用的,就會(huì)將它轉(zhuǎn)換為原始類型,JVM中只含有原始類型,所以上面的理解是錯(cuò)誤的,泛型對(duì)運(yùn)行時(shí)是毫無意義的,更談不上提高效率。

正由于泛型的這個(gè)特點(diǎn),所以不能用泛型類型參數(shù)創(chuàng)建實(shí)例
E object = new E(); // false

此外,不能用泛型類型參數(shù)創(chuàng)建數(shù)組
E[] elements = new E [capacity]; //false

同時(shí)不建議使用強(qiáng)制類型轉(zhuǎn)換
E[] elements = (E[])new Object [capacity];
如果 E 是 String,而 new Object[] 是 Integer 對(duì)象的數(shù)組,那么 (String[]) (new Object[]) 將會(huì)導(dǎo)致 ClassCastException 異常。

在靜態(tài)環(huán)境下、異常類也是不能使用泛型的。

下面我們來觀察一個(gè)例子:

import java.util.ArrayList;
import java.util.List;

class A {
}

class B extends A {
}

class D extends B {
}

public class TestGenericType {
    public static void main(String[] args) {

        List list = new ArrayList();
        List<A> listA = new ArrayList<A>();
        list = listA;// A正確

        List<B> listB = new ArrayList<B>();
        // listA=listB;//B錯(cuò)誤

        List<Object> listObject = new ArrayList<Object>();
        List<?> list$ = new ArrayList<>();
        list$ = listObject;// C正確

        List<D> listD = new ArrayList<D>();
        List<? extends B> listExtendsB = new ArrayList<>();
        listExtendsB = listD;// D正確

        List<? extends A> listExtendsA = new ArrayList<>();
        // listA = listExtendsA;//E錯(cuò)誤

        listExtendsA = listExtendsB;// F正確

        List<? super B> listSuperB = new ArrayList<>();
        listSuperB = listB;// G正確

        // listSuperB = listExtendsB;//H錯(cuò)誤
    }

}

其中, ? 、 ? extends T 、 ? super T 是通配泛型。
? --->非受限通配,它和 ? extends Object 一樣
? extends T --->受限通配,表示 T 或 T 的一個(gè)未知子類型
? super T --->下限通配,表示 T 或 T 的一個(gè)未知父類型

它們的關(guān)系如下圖(摘自《Java語言程序設(shè)計(jì)》進(jìn)階篇)

Paste_Image.png

我們來做下分析:
【A】由第一張圖的例子可知,listA instanceof list
【B】盡管 B 是 A 的子類,但 List<B> 不是 List<A> 的子類,所以 listA = listB 是錯(cuò)誤的
【C】? 同等于 ? extends Object,list$ 能接收 Object 或 Object 的一個(gè)未知子類型,所以能接收 listObject
【D】解釋同“C”
【E】同“A”,若 listExtendsA 接收的是 B 類,則 List<B> 不是 List<A> 的子類
【F】listExtendsA 能接收 A 或 A 的子類,正確
【G】listSuperB 能接收 B 或 B 的父類,正確
【H】listSuperB 不能接收 B 的子類,listExtendsB 可能接收 D類

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • Scala與Java的關(guān)系 Scala與Java的關(guān)系是非常緊密的!! 因?yàn)镾cala是基于Java虛擬機(jī),也就是...
    燈火gg閱讀 3,479評(píng)論 1 24
  • 開發(fā)人員在使用泛型的時(shí)候,很容易根據(jù)自己的直覺而犯一些錯(cuò)誤。比如一個(gè)方法如果接收List作為形式參數(shù),那么如果嘗試...
    時(shí)待吾閱讀 1,072評(píng)論 0 3
  • 為什么需要泛型? 通過泛型可以定義類型安全的數(shù)據(jù)結(jié)構(gòu),而無須使用實(shí)際的數(shù)據(jù)類型(可擴(kuò)展)。這能夠顯著提高性能并得到...
    一只好奇的茂閱讀 1,272評(píng)論 2 39
  • 我好像多讀了兩章,今天就給自己一個(gè)懶的理由,這兩天一直在讀前世今生,不知道為啥就是對(duì)這個(gè)特別感興趣,繼續(xù)看!
    小怪獸_d0c7閱讀 163評(píng)論 0 0
  • 我總是覺得美好得事物值得被等待,殊不知,等待卻蹉跎了最好得時(shí)光。 也許有人會(huì)說你眼高于頂,認(rèn)為你好高騖遠(yuǎn),或者覺得...
    隱沐在人間閱讀 636評(píng)論 0 1