日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

java泛型(一)、泛型的基本介绍和使用

發(fā)布時間:2024/1/23 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java泛型(一)、泛型的基本介绍和使用 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

?轉(zhuǎn)載地址 ?http://m.blog.csdn.net/article/details?id=7864531

現(xiàn)在開始深入學(xué)習(xí)java的泛型了,以前一直只是在集合中簡單的使用泛型,根本就不明白泛型的原理和作用。泛型在java中,是一個十分重要的特性,所以要好好的研究下。

一、泛型的基本概念

?泛型的定義:泛型是JDK 1.5的一項新特性,它的本質(zhì)是參數(shù)化類型(Parameterized Type)的應(yīng)用,也就是說所操作的數(shù)據(jù)類型被指定為一個參數(shù),在用到的時候在指定具體的類型。這種參數(shù)類型可以用在類、接口和方法的創(chuàng)建中,分別稱為泛型類、泛型接口和泛型方法。

? 泛型思想早在C++語言的模板(Templates)中就開始生根發(fā)芽,在Java語言處于還沒有出現(xiàn)泛型的版本時,只能通過Object是所有類型的父類和類型強制轉(zhuǎn)換兩個特點的配合來實現(xiàn)類型泛化。例如在哈希表的存取中,JDK 1.5之前使用HashMap的get()方法,返回值就是一個Object對象,由于Java語言里面所有的類型都繼承于java.lang.Object,那Object轉(zhuǎn)型為任何對象成都是有可能的。但是也因為有無限的可能性,就只有程序員和運行期的虛擬機才知道這個Object到底是個什么類型的對象。在編譯期間,編譯器無法檢查這個Object的強制轉(zhuǎn)型是否成功,如果僅僅依賴程序員去保障這項操作的正確性,許多ClassCastException的風(fēng)險就會被轉(zhuǎn)嫁到程序運行期之中。

? 泛型技術(shù)在C#和Java之中的使用方式看似相同,但實現(xiàn)上卻有著根本性的分歧,C#里面泛型無論在程序源碼中、編譯后的IL中(Intermediate Language,中間語言,這時候泛型是一個占位符)或是運行期的CLR中都是切實存在的,List<int>與List<String>就是兩個不同的類型,它們在系統(tǒng)運行期生成,有自己的虛方法表和類型數(shù)據(jù),這種實現(xiàn)稱為類型膨脹,基于這種方法實現(xiàn)的泛型被稱為真實泛型。

? Java語言中的泛型則不一樣,它只在程序源碼中存在,在編譯后的字節(jié)碼文件中,就已經(jīng)被替換為原來的原始類型(Raw Type,也稱為裸類型)了,并且在相應(yīng)的地方插入了強制轉(zhuǎn)型代碼,因此對于運行期的Java語言來說,ArrayList<int>與ArrayList<String>就是同一個類。所以說泛型技術(shù)實際上是Java語言的一顆語法糖,Java語言中的泛型實現(xiàn)方法稱為類型擦除,基于這種方法實現(xiàn)的泛型被稱為偽泛型。(類型擦除在后面在學(xué)習(xí))

? 使用泛型機制編寫的程序代碼要比那些雜亂的使用Object變量,然后再進行強制類型轉(zhuǎn)換的代碼具有更好的安全性和可讀性。泛型對于集合類來說尤其有用。

? 泛型程序設(shè)計(Generic Programming)意味著編寫的代碼可以被很多不同類型的對象所重用。


實例分析:

? 在JDK1.5之前,Java泛型程序設(shè)計是用繼承來實現(xiàn)的。因為Object類是所用類的基類,所以只需要維持一個Object類型的引用即可。就比如ArrayList只維護一個Object引用的數(shù)組:

public class ArrayList//JDK1.5之前的 {public Object get(int i){......}public void add(Object o){......}......private Object[] elementData; } 這樣會有兩個問題:

1、沒有錯誤檢查,可以向數(shù)組列表中添加類的對象

2、在取元素的時候,需要進行強制類型轉(zhuǎn)換

這樣,很容易發(fā)生錯誤,比如:

/**jdk1.5之前的寫法,容易出問題*/ArrayList arrayList1=new ArrayList();arrayList1.add(1);arrayList1.add(1L);arrayList1.add("asa");int i=(Integer) arrayList1.get(1);//因為不知道取出來的值的類型,類型轉(zhuǎn)換的時候容易出錯 這里的第一個元素是一個長整型,而你以為是整形,所以在強轉(zhuǎn)的時候發(fā)生了錯誤。

所以。在JDK1.5之后,加入了泛型來解決類似的問題。例如在ArrayList中使用泛型:

/** jdk1.5之后加入泛型*/ArrayList<String> arrayList2=new ArrayList<String>(); //限定數(shù)組列表中的類型 // arrayList2.add(1); //因為限定了類型,所以不能添加整形 // arrayList2.add(1L);//因為限定了類型,所以不能添加整長形arrayList2.add("asa");//只能添加字符串String str=arrayList2.get(0);//因為知道取出來的值的類型,所以不需要進行強制類型轉(zhuǎn)換

還要明白的是,泛型特性是向前兼容的。盡管 JDK 5.0 的標(biāo)準(zhǔn)類庫中的許多類,比如集合框架,都已經(jīng)泛型化了,但是使用集合類(比如 HashMap 和 ArrayList)的現(xiàn)有代碼可以繼續(xù)不加修改地在 JDK 1.5 中工作。當(dāng)然,沒有利用泛型的現(xiàn)有代碼將不會贏得泛型的類型安全的好處。


在學(xué)習(xí)泛型之前,簡單介紹下泛型的一些基本術(shù)語,以ArrayList<E>ArrayList<Integer>做簡要介紹:

整個成為ArrayList<E>泛型類型

ArrayList<E>中的?E稱為類型變量或者類型參數(shù)

整個ArrayList<Integer>?稱為參數(shù)化的類型

ArrayList<Integer>中的integer稱為類型參數(shù)的實例或者實際類型參數(shù)

·ArrayList<Integer>中的<Integer>念為typeof?? Integer

ArrayList稱為原始類型


二、泛型的使用

泛型的參數(shù)類型可以用在類、接口和方法的創(chuàng)建中,分別稱為泛型類、泛型接口和泛型方法。下面看看具體是如何定義的。

1、泛型類的定義和使用

一個泛型類(generic class)就是具有一個或多個類型變量的類。定義一個泛型類十分簡單,只需要在類名后面加上<>,再在里面加上類型參數(shù):

class Pair<T> {private T value;public Pair(T value) {this.value=value;}public T getValue() {return value;}public void setValue(T value) {this.value = value;} }現(xiàn)在我們就可以使用這個泛型類了:
public static void main(String[] args) throws ClassNotFoundException {Pair<String> pair=new Pair<String>("Hello");String str=pair.getValue();System.out.println(str);pair.setValue("World");str=pair.getValue();System.out.println(str);}

Pair類引入了一個類型變量T,用尖括號<>括起來,并放在類名的后面。泛型類可以有多個類型變量。例如,可以定義Pair類,其中第一個域和第二個域使用不同的類型:

public class Pair<T,U>{......}

注意:類型變量使用大寫形式,且比較短,這是很常見的。在Java庫中,使用變量E表示集合的元素類型,K和V分別表示關(guān)鍵字與值的類型。(需要時還可以用臨近的字母U和S)表示“任意類型”。


2、泛型接口的定義和使用

定義泛型接口和泛型類差不多,看下面簡單的例子:

interface Show<T,U>{void show(T t,U u); }class ShowTest implements Show<String,Date>{@Overridepublic void show(String str,Date date) {System.out.println(str);System.out.println(date);} } 測試一下:

public static void main(String[] args) throws ClassNotFoundException {ShowTest showTest=new ShowTest();showTest.show("Hello",new Date());}
3、泛型方法的定義和使用

泛型類在多個方法簽名間實施類型約束。在 List<V> 中,類型參數(shù) V 出現(xiàn)在 get()、add()、contains() 等方法的簽名中。當(dāng)創(chuàng)建一個 Map<K, V> 類型的變量時,您就在方法之間宣稱一個類型約束。您傳遞給 add() 的值將與 get() 返回的值的類型相同。

類似地,之所以聲明泛型方法,一般是因為您想要在該方法的多個參數(shù)之間宣稱一個類型約束。

舉個簡單的例子:

public static void main(String[] args) throws ClassNotFoundException {String str=get("Hello", "World");System.out.println(str);}public static <T, U> T get(T t, U u) {if (u != null)return t;elsereturn null;}

三、泛型變量的類型限定

在上面,我們簡單的學(xué)習(xí)了泛型類、泛型接口和泛型方法。我們都是直接使用<T>這樣的形式來完成泛型類型的聲明。

有的時候,類、接口或方法需要對類型變量加以約束。看下面的例子:

有這樣一個簡單的泛型方法:

public static <T> T get(T t1,T t2) {if(t1.compareTo(t2)>=0);//編譯錯誤return t1;} 因為,在編譯之前,也就是我們還在定義這個泛型方法的時候,我們并不知道這個泛型類型T,到底是什么類型,所以,只能默認(rèn)T為原始類型Object。所以它只能調(diào)用來自于Object的那幾個方法,而不能調(diào)用compareTo方法。

可我的本意就是要比較t1和t2,怎么辦呢?這個時候,就要使用類型限定,對類型變量T設(shè)置限定(bound)來做到這一點。

我們知道,所有實現(xiàn)Comparable接口的方法,都會有compareTo方法。所以,可以對<T>做如下限定:

public static <T extends Comparable> T get(T t1,T t2) { //添加類型限定if(t1.compareTo(t2)>=0);return t1;}
類型限定在泛型類、泛型接口和泛型方法中都可以使用,不過要注意下面幾點:

1、不管該限定是類還是接口,統(tǒng)一都使用關(guān)鍵字 extends

2、可以使用&符號給出多個限定,比如

public static <T extends Comparable&Serializable> T get(T t1,T t2) 3、如果限定既有接口也有類,那么類必須只有一個,并且放在首位置

public static <T extends Object&Comparable&Serializable> T get(T t1,T t2)

總結(jié)

以上是生活随笔為你收集整理的java泛型(一)、泛型的基本介绍和使用的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。