java進階特性之泛型__java基礎

來源:互聯網
上載者:User

泛型擦除

反射機制

自訂泛型類

自訂類型方法

java泛類型相關知識

1 為什麼使用泛型

解決元素儲存時候的安全性問題,同時解決擷取集合元素的時候類型強轉的問題。

提高代碼的重用率。

例如編寫一個泛型類,而我們不去關心類的具體類型,而用T來代表其變化的類型。T不能代表基礎資料型別 (Elementary Data Type)。

泛型注意:

在使用泛型的運算式中,如果兩邊都使用了泛型,那麼兩邊的泛型必須一致。

如果運算式只有一邊使用了泛型,那麼運算式的另一邊可以不使用泛型。

(如果任何類型的資料都可以添加到集合中,造成集合類型不安全,另外讀取出來的對象可能需要轉換,使用繁瑣,容易出現)

泛型中的幾個概念:

以ArrayList為例,<>念做 typeof

ArrayList中的E,稱為型別參數變數

ArrayList中的Integer被稱為實際型別參數

整個ArrayLIst泛型型別

整個ArrayList稱為參數化類別型ParameterizedType.

ClassCastException(類轉換異常)

如下代碼:

ArrayList a1 = new ArrayList();

a1.add(dog);

a1.add(cat);

Dog temp = a1.get(0);

System.out.println(a1.get(0));

Dog temp = (Dog) a1.get(0);

//dog是Dog類的一個執行個體

首先定義了一個ArrayList 類型的集合,然後往集合裡面添加了Dog類型的對象以及Cat類型的對象,這裡是完全允許的,因為所有的類型集合都預設為Object類,在javac階段也沒有問題,但是在java階段(運行階段)就會出現類型轉換的異常,ClassCastException。

分析:

1.當我們將一個對象放入集合的時候,集合不會記住對象的類型,當再次從集合中取出對象的時候,該對象的編譯類型為Object類型,而運行時類型任何為其本身的類型。

2.若想使用該對象,必須要做強制轉換。

【摘自某部落格】

【泛型,JDK1.5新加入的,解決資料類型的安全性問題,其主要原理是在類聲明時通過一個標識表示類中某個屬性的類型或者是某個方法的傳回值及參數類型。這樣在類聲明或執行個體化時只要指定好需要的具體的類型即可。】

【安全隱患的理解】:

在java1.5之前,沒有泛型的情況下,通過對類型Object 的引用來實現參數的“任意化”,任意化帶來的確定就是要做顯示的強制類型轉換,而且要求開發人員必須對實際參數類型預知的情況下進行,而且對於強制類型轉換錯誤的情況下,javac不會顯示錯誤,在啟動並執行時候才會異常,導致jvm崩潰。這是一個安全的隱患。

參考代碼TestGenerics.java

泛型類

泛型類的聲明:

class/interface name

//當通過對象調泛型方法時,指明泛型方法的類型。public <E> List<E> fromArrayToList(E[] e,List<E> list){for(E xx : e){list.add(xx);}return list;}//List<Integer> list3 = order.fromArrayToList(in, list2);

泛型與繼承:

若類B是類A的子類,那麼List < B >和 List< A >沒有繼承關係。

若想在泛型中使用繼承,那麼可以使用萬用字元。

List< B > 和List< A >都是List< ? >的子類

List< ? extends A>可以存放類A及其子類的

List< ? super A> 可以存放類A及其父類

使用萬用字元的集合:

List< ? > list :可以從使用萬用字元的集合list中擷取資料,其元素類型為Object。不可以往萬用字元的集合中list添加資料除了null之外。

泛型擦除

我們發現,在使用泛型類時,雖然傳入了不同的泛型實參,但並沒有真正意義上產生不同的類型, 傳入不同泛型實參的泛型類在記憶體上只有一個,即還是原來的最基本的類型(new 出來的對象是何種類型,那麼它在記憶體上就是什麼類型), 當然,在邏輯上我們可以理解成多個不同的泛型型別。

究其原因,在於Java中的泛型這一概念提出的目的,導致其只是作用於代碼編譯階段,在編譯過程中,對於正確檢驗泛型結果後,會將泛型的相關資訊擦出,也就是說,成功編譯過後的class檔案中是不包含任何泛型資訊的。泛型資訊不會進入到運行時階段。

對此總結成一句話:泛型類在邏輯上看以看成是多個不同的類型,實際上都是相同的類型。【泛型擦出】

java核心技術一書中的觀點:
jvm中沒有泛型型別的對象,所有的對象都是普通對象。無論何時定義了一個泛型型別,都自動的提供了一個相應的原始類型,(raw type),原始類型的名字就是刪除了型別參數後的泛型型別名,擦除(erased)類型變數,並替代類限定類型。
翻譯泛型運算式:
由於泛型擦除機制,編譯器會將泛型方法翻譯為2條虛擬機器指定
1調用原始的方法
2對於返回的Object類型的資料強制類型轉換為泛型型別。
總之需要記住有關java泛型轉換的事實:
1,虛擬機器中沒有泛型,只有普通的類和方法
2,所有的型別參數都是由他們的限定類型替換
3,橋方法被合成用來保持多態
4,為保持類型的安全性,必要時插入強制類型轉換。

反射和泛型

Class類是泛型的,String.class實際上是Class類的對象,也是唯一的對象。
型別參數十分有用,因為它允許Class方法的傳回型別更加具有針對性。

JVM中的泛型型別資訊
java泛型的卓越特性就是泛型擦除,被擦除的類型仍然可以通過反射API擷取泛型資訊。
如下方法:
public static < T extends Comparable < ? supper T>> T min(T[] a)

通過反射API可以擷取:
在SE5.0之後,新的介面Type,這個介面下包含的子類型:
Class:描述具體類型
TypeVariable介面:描述類型變數(Textends Comparable < ? supper T>)
WildcardType介面:描述萬用字元(如。supper T)
ParameterizedType介面:描述泛型類或者介面類型(Comparable < ? supper T>)
GenericArrayType介面:描述泛型數組 T[] a

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.