java怎么使用泛型_java泛型 7 泛型的基本介紹和使用

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

一、泛型的基本概念

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

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

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

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

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

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

實例分析:

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

public?class?ArrayList//JDK1.5之前的

{

public?Object?get(int?i){......}

public?void?add(Object?o){......}

......

private?Object[]?elementData;

}

這樣會有兩個問題:

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

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

這樣,很容易發生錯誤,比如:

/**jdk1.5之前的寫法,容易出問題*/

ArrayList?arrayList1=new?ArrayList();

arrayList1.add(1);

arrayList1.add(1L);

arrayList1.add("asa");

int?i=(Integer)?arrayList1.get(1);//因為不知道取出來的值的類型,類型轉換的時候容易出錯

這里的第一個元素是一個長整型,而你以為是整形,所以在強轉的時候發生了錯誤。

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

/**?jdk1.5之后加入泛型*/

ArrayList?arrayList2=new?ArrayList();??//限定數組列表中的類型

//??????arrayList2.add(1);?//因為限定了類型,所以不能添加整形

//??????arrayList2.add(1L);//因為限定了類型,所以不能添加整長形

arrayList2.add("asa");//只能添加字符串

String?str=arrayList2.get(0);//因為知道取出來的值的類型,所以不需要進行強制類型轉換

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

在學習泛型之前,簡單介紹下泛型的一些基本術語,以ArrayList和ArrayList做簡要介紹:

整個成為ArrayList泛型類型

ArrayList中的?E稱為類型變量或者類型參數

整個ArrayList?稱為參數化的類型

ArrayList中的integer稱為類型參數的實例或者實際類型參數

·ArrayList中的念為typeof?? Integer

ArrayList稱為原始類型

二、泛型的使用

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

1、泛型類的定義和使用

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

class?Pair?{

private?T?value;

public?Pair(T?value)?{

this.value=value;

}

public?T?getValue()?{

return?value;

}

public?void?setValue(T?value)?{

this.value?=?value;

}

}

現在我們就可以使用這個泛型類了:

public?static?void?main(String[]?args)?throws?ClassNotFoundException?{

Pair?pair=new?Pair("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{......}

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

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

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

interface?Show{

void?show(T?t,U?u);

}

class?ShowTest?implements?Show{

@Override

public?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 出現在 get()、add()、contains() 等方法的簽名中。當創建一個 Map 類型的變量時,您就在方法之間宣稱一個類型約束。您傳遞給 add() 的值將與 get() 返回的值的類型相同。

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

舉個簡單的例子:

public?static?void?main(String[]?args)?throws?ClassNotFoundException?{

String?str=get("Hello",?"World");

System.out.println(str);

}

public?static??T?get(T?t,?U?u)?{

if?(u?!=?null)

return?t;

else

return?null;

}

三、泛型變量的類型限定

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

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

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

public?static??T?get(T?t1,T?t2)?{

if(t1.compareTo(t2)>=0);//編譯錯誤

return?t1;

}

因為,在編譯之前,也就是我們還在定義這個泛型方法的時候,我們并不知道這個泛型類型T,到底是什么類型,所以,只能默認T為原始類型Object。所以它只能調用來自于Object的那幾個方法,而不能調用compareTo方法。

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

我們知道,所有實現Comparable接口的方法,都會有compareTo方法。所以,可以對做如下限定:

public?static??T?get(T?t1,T?t2)?{?//添加類型限定

if(t1.compareTo(t2)>=0);

return?t1;

}

類型限定在泛型類、泛型接口和泛型方法中都可以使用,不過要注意下面幾點:

1、不管該限定是類還是接口,統一都使用關鍵字 extends

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

public?static??T?get(T?t1,T?t2)

3、如果限定既有接口也有類,那么類必須只有一個,并且放在首位置

public?static??T?get(T?t1,T?t2)

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/443222.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/443222.shtml
英文地址,請注明出處:http://en.pswp.cn/news/443222.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

java鋁輪_為速度而生 JAVA Fuoco鋁合金氣動公路

人類在追求速度的歷史上一直在不斷創新&#xff0c;從兩個輪子的自行車&#xff0c;到四個輪字的汽車&#xff0c;再到螺旋槳的飛機&#xff0c;追求速度是人類與生俱來的天性。就如同公路車的用途非常多&#xff0c;綜合型公路車、耐力型公路車、爬坡型公路車&#xff0c;但唯…

erlang mysql性能瓶頸,Erlang Mysql:如何防止SQL注入

Im very new to erlang and I need to code something which inserts rows in a MySQL Database.How can I prevent SQL Injections with Erlang? Is there also something like prepared statements in other Languages or how should I do it?Thanks for your replies.解決…

下列哪個不是java的數據類型_下面哪個不是Java基本數據類型?()

采集血標本時&#xff0c;錯誤的操作是A&#xff0e;血清標本應注入干燥試管B&#xff0e;生化檢驗標本在空腹時采集試比較脂肪酸β&#xff0d;氧化與生物合成的差異。調節水平衡的激素主要是A.胰島素 B.甲狀旁腺激素 C.血管升壓素 D求比50克多5克的數是多少&#xff1f;列式是…

Java jpa 字段限制_Java-JPA:僅更新特定字段

我有同樣的問題&#xff0c;正如Deinum先生所指出的&#xff0c;答案是否定的&#xff0c;您不能使用save。 主要問題是Spring Data不知道如何處理null。 是否設置了空值&#xff0c;還是因為需要將其刪除而設置了空值&#xff1f;現在從您的問題來看&#xff0c;我認為您也有同…

java excel中刪除兩列_Java 插入、隱藏/顯示、刪除Excel行或列

概述操作Excel工作表時&#xff0c;對表格中的行或列數據可執行&#xff0c;包括插入、隱藏、顯示、刪除等在內的多種操作需求&#xff0c;本文將通過Java代碼示例演示每種操作的具體實現方法。文中方法使用了Java Excel類庫(Free Spire.XLS for Java 免費版)&#xff0c;可通過…

java屏蔽編譯告警_java-禁止JAXB生成的類上的編譯器警告

這可能是該問題的副本(Avoiding Compiler warnings on code generated by xjc),但是由于我不太了解XJC / JAXB自定義綁定特質,所以我想我可能誤解了所提到的問題.我的問題似乎很簡單-如何將SuppressWarnings(“ all”)批注添加到生成的JAXB類中&#xff1f;我們的項目有0個警告…

Java中number數字類型的轉換_Java下數字類型的轉換 (轉)

Java下數字類型的轉換 (轉)[more]作者&#xff1a;家居貓各種數字類型轉換成字符串型&#xff1a;String s String.valueOf( value); // 其中 value 為任意一種數字類型。字符串型轉換成各種數字類型&#xff1a;String s "169";byte b Byte.parseByte( s );short…

Java0steam_Java學習 - Stream 使用

Java Stream使用這段時間在學數據庫和Java&#xff0c;發現Java的Stream實際上和數據庫的查詢操作非常類似。這里簡單介紹Stream的用法&#xff0c;并和Sql Server中的操作聯系起來。此文為初學Stream所寫&#xff0c;以后對Stream有更深的理解后會重寫當我們使用一個流的時候&…

mysql初始化很慢_mysql初始化報錯

/var/log/mysql.log 日志報錯如上圖所示解決方法&#xff1a;SELinux惹的禍通俗的講就是linux服務器的安全策略解決&#xff1a;臨時關閉&#xff1a;setenforce 0永久關閉需要修改配置文件&#xff0c;重啟機器&#xff1a;修改/etc/selinux/config 文件將SELINUXenforcing改為…

百度java的線程技術_自我提升(基礎技術篇)——java線程簡介

前言&#xff1a;雖然自己平時都在用多線程&#xff0c;也能完成基本的工作需求&#xff0c;但總覺得&#xff0c;還是對線程沒有一個系統的概念&#xff0c;所以&#xff0c;查閱了一些資料&#xff0c;理解那些大神和官方的資料&#xff0c;寫這么一篇關于線程的文章本來想廢…

java調用掃描儀識別文字_Java使用掃描儀讀取文件輸入

示例Scanner scanner null;try {scanner new Scanner(new File("Names.txt"));while (scanner.hasNext()) {System.out.println(scanner.nextLine());}} catch (Exception e) {System.err.println("發生異常&#xff01;");} finally {if (scanner ! nul…

d3 tip mysql_mysql

字符&#xff1a;char(10)->定長、10個字符寬度。如果右側不夠&#xff0c;則空格補齊&#xff0c;取出來的時候刪除空格。varchar(10)->變長、最多10個字符如&#xff1a;存姓名的時候&#xff0c;沒必要為了那幾個長度去使用varchar&#xff0c;使用定長去存儲會提高效…

java string rt_如何使jvm加載我的java.lang.String而不是rt.jar中的那個

我認真研究了Java類加載器。現在&#xff0c;我想編寫一個與rt.jar中的類之一具有相同的包名稱和類名稱的類。例如&#xff0c;我自己編寫一個java.lang.String類&#xff0c;以及如何打破父級委托模型以使jvm加載我的java.lang.String而不是rt.jar中的類。重新編輯Thx&#xf…

php在線語音,PHP在線語音合成

這篇文章主要介紹了PHP在線語音合成&#xff0c;有著一定的參考價值&#xff0c;現在分享給大家&#xff0c;有需要的朋友可以參考一下在線語音合成 PHP SDKhttp://yuyin.baidu.com/docs/tts/194PHP SDK文檔簡介Hi&#xff0c;您好&#xff0c;歡迎使用百度語音合成服務。本文檔…

php工廠模式和單例模式,php 設計模式之工廠模式、單例模式、注冊樹模式

php 設計模式之工廠模式、單例模式、注冊樹模式在軟件工程中&#xff0c;創建型設計模式承擔著對象創建的職責&#xff0c;嘗試創建適合程序上下文的對象&#xff0c;對象創建設計模式的產生是由于軟件工程設計的問題&#xff0c;具體說是向設計中增加復雜度&#xff0c;創建型…

php 正則匹配unicode,PHP中正則表達式對UNICODE字符碼的匹配方法

網友ainiaa的問題是PHP代碼如下代碼如下:$words "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSRUVWXYZ!#$%^&*()_-[]\\,./{}|<>?\"你好啊我們";$otherStrpreg_replace("/[chr(128)-chr(256)]/is"," ",$words);ech…

iis7怎么安裝php7,Linux下如何安裝php7

Linux下安裝php7的方法&#xff1a;首先安裝依賴包&#xff0c;并下載解壓安裝包&#xff1b;然后檢查環境的依賴關系&#xff0c;并編譯安裝&#xff1b;接著將【php.ini-production】改名為【php.ini】&#xff1b;最后復制啟動腳本&#xff0c;并啟動PHP即可。Linux下安裝ph…

php長輪詢阻塞,ajax長輪詢時php被阻塞

剛接觸實時通訊這塊&#xff0c;知道用websocket更高效&#xff0c;但我想了解輪詢的實現過程&#xff0c;循序漸進短輪詢用定時器setInterval已經實現了&#xff0c;但長輪詢時后臺進入死循環模塊導致整個網站的php網頁無響應&#xff0c;比如刷新頁面、提交消息都沒法進行。具…

php隱藏路徑ngnix,thinkphp框架在nginx環境下去掉index.php路徑顯示

協助用戶將apache下的一個網站遷移到nginx環境中&#xff0c;結果發現用戶用的ThinkPHP框架做的開發&#xff0c;默認用的pathinfo。這是一個很頭疼的問題&#xff0c;因為nginx不支持pathinfo&#xff0c;貿然一并打開也擔心不安全。于是查詢資料后整理如下&#xff1a;找到ap…

php curl 數據采集 空,PHP curl從網站返回空數組的數據

我想寫一個PHP腳本來從www.snowbird.com/mountain-report/拉雪和其他數據通過LED陣列顯示。我在獲取需要的數據方面遇到麻煩。我似乎無法找到使其工作的方法。我能做這項工作嗎&#xff1f;還是我需要去使用另一種語言&#xff1f;PHP curl從網站返回空數組的數據以下代碼僅返回…