中文在线免费看视频_国产成人精品亚洲日本在线观看_亚洲精品第一综合99久久_国产亚洲精品日韩综合网

當(dāng)前位置: 首頁(yè) / 技術(shù)干貨 / 正文
民哥帶你快速精通java泛型(一)

2022-10-18

泛型 類型   

  泛型由入門到精通

  Hi,小伙伴你好~歡迎進(jìn)入泛型的學(xué)習(xí),在學(xué)習(xí)之前友情提醒一下:學(xué)習(xí)泛型需要小伙伴們具備一定的javaSE基礎(chǔ),如果之前小伙伴們沒(méi)有接觸過(guò)java,大家可以移步到千鋒北京java好程序員的javaSE課程進(jìn)行學(xué)習(xí)。

  在正式開(kāi)始學(xué)習(xí)之前,我們先來(lái)看一段經(jīng)常書(shū)寫(xiě)的代碼,分析一下代碼存在那些問(wèn)題?

  代碼如下:

public class GenericsDemo {
public static void main(String[] args) {
//1.創(chuàng)建一個(gè)List對(duì)象
List list = new ArrayList();
//2.向List中添加數(shù)據(jù)
list.add("python");
list.add("java");
list.add(66);
//3.遍歷集合
for (int i = 0; i <list.size() ; i++) {
//4.把集合中的每個(gè)元素轉(zhuǎn)成String類型
String ele = (String) list.get(i);
//5.打印-測(cè)試結(jié)果
System.out.println("元素的值:"+ele);
}
}
}

  運(yùn)行代碼,會(huì)報(bào)如下圖的異常:

a1

  那么小伙們,我們來(lái)分析一下原因,到底是因?yàn)槭裁磮?bào)這個(gè)異常呢?

  在代碼中我們定義了一個(gè)List類型的集合,先向其中加入了兩個(gè)String類型的值,隨后加入一個(gè)Integer類型的值。這是完全允許的,因?yàn)榇藭r(shí)list默認(rèn)的類型為Object類型,所以在代碼編譯期間沒(méi)有任何問(wèn)題。

  但是在運(yùn)行代碼時(shí),由于list集合中既有String類型的值,又有Integer類型的值,致使list集合無(wú)法區(qū)分值是什么類型,很容易出現(xiàn)上圖中的錯(cuò)誤。因?yàn)榫幾g階段正常,而運(yùn)行時(shí)會(huì)出現(xiàn)“java.lang.ClassCastException”異常。因此導(dǎo)致此類錯(cuò)誤編碼過(guò)程中不易發(fā)現(xiàn)。

  分析完了,小伙們現(xiàn)在明白了吧,通過(guò)分析我們發(fā)現(xiàn)上述代碼主要存在兩個(gè)問(wèn)題:

  當(dāng)我們將數(shù)據(jù)存入集合時(shí),集合不會(huì)記住數(shù)據(jù)的類型,默認(rèn)數(shù)據(jù)類型都是Object。

  當(dāng)我們遍歷集合中的數(shù)據(jù)時(shí),人為進(jìn)行強(qiáng)制類型轉(zhuǎn)換,很容易報(bào)“java.lang.ClassCastException”。強(qiáng)制類型轉(zhuǎn)換異常

  那么有沒(méi)有什么辦法可以使集合能夠記住集合內(nèi)元素各類型,且能夠達(dá)到只要編譯時(shí)不出現(xiàn)問(wèn)題,運(yùn)行時(shí)就

  不會(huì)出現(xiàn)“java.lang.ClassCastException”異常呢?

  答案就是使用泛型。

  那么什么是泛型呢?

  第一關(guān) 讓我們一起走入泛型

  1.泛型的概述

  1.1 什么是泛型

  泛型,泛指任意類型,可以應(yīng)用在接口上,類上,變量上,方法上,以及方法的參數(shù)中。

  百度百科介紹:

  泛型是jdk1.5的新特性,泛型的本質(zhì)是參數(shù)化類型,也就是說(shuō)所操作的數(shù)據(jù)類型被指定為一個(gè)參數(shù)。這種參數(shù)類型可以用在類、接口和方法的創(chuàng)建中,分別稱為泛型類、泛型接口、泛型方法。

  在jdk1.5之前,沒(méi)有泛型的情況的下,通過(guò)對(duì)類型Object的引用來(lái)實(shí)現(xiàn)參數(shù)的“任意化”,“任意化”帶來(lái)的缺點(diǎn)是要做顯式的強(qiáng)制類型轉(zhuǎn)換,而這種轉(zhuǎn)換是要求開(kāi)發(fā)者對(duì)實(shí)際參數(shù)類型可以預(yù)知的情況下進(jìn)行的。對(duì)于強(qiáng)制類型轉(zhuǎn)換錯(cuò)誤的情況 ,編譯器可能不提示錯(cuò)誤,在運(yùn)行的時(shí)候才出現(xiàn)異常,這是一個(gè)安全隱患。

  泛型的好處:使用泛型,首先可以通過(guò)IDE進(jìn)行代碼類型初步檢查,然后在編譯階段進(jìn)行編譯類型檢查,以保證類型轉(zhuǎn)換的安全性;并且所有的強(qiáng)制轉(zhuǎn)換都是自動(dòng)和隱式的,可以提高代碼的重用率。

  個(gè)人理解:

  簡(jiǎn)單來(lái)說(shuō):泛型,即“參數(shù)化類型”,那么類型“參數(shù)化”到底怎么理解呢?

  顧名思義,類型“參數(shù)化”就是將類型由原來(lái)的具體類型,變成參數(shù)化的“類型”,有點(diǎn)類似于方法中的變量參數(shù),不過(guò)此時(shí)是類型定義成參數(shù)形式(你可以理解為類型形參),然后在使用時(shí)傳入具體的類型(也就是類型實(shí)參)。為什么這樣操作呢?因?yàn)樗茏岊愋?參數(shù)化",也就是在不創(chuàng)建新的類型的情況下,通過(guò)泛型可以指定不同類型來(lái)控制形參具體限制的類型。

  總結(jié):

  泛型介紹完了, 小伙伴看完上述解釋后,能理解泛型是什么了嗎?我們可以用兩句話來(lái)概括一下:

  泛型在聲明時(shí),用標(biāo)記符表示,僅僅作為“參數(shù)化的類型”,可以理解為形式參數(shù)。

  比如:

  //定義List集合時(shí),用標(biāo)記符E表示任意類型,E可以理解為形式參數(shù),沒(méi)有具體的類型值public interface Listextends Collection{ ----------}

  泛型在使用時(shí),需要指定具體的類型,也就是類型實(shí)際的參數(shù)。

  比如:

  //在使用List集合時(shí),需要確定E的具體類型,String可以理解為具體的類型,也就是實(shí)際的參數(shù)值Listlist = new ArrayList();

  1.2 常用的泛型標(biāo)記符

  E - Element (集合使用,因集合中存放元素)

  T - Type(Java 類)

  K - Key(鍵) V - Value(值)

  N - Number(數(shù)值類型)

  ? - 表示不確定的java類型

  S、U、V - 2nd、3rd、4th types

  你可能會(huì)有疑問(wèn),弄這么多標(biāo)識(shí)符干嘛,直接使用萬(wàn)能的Object難道不香么?我們知道Object是所有類的基類(任何類如果沒(méi)有指明其繼承類,都默認(rèn)繼承于Object類),因此任何類的對(duì)象都可以設(shè)置Object的引用,只不過(guò)在使用的時(shí)候可能要類型強(qiáng)制轉(zhuǎn)換。但是如果設(shè)置了泛型E、T等這些標(biāo)識(shí)符,那么在實(shí)際使用之前類型就已經(jīng)確定,因此不再需要類型強(qiáng)制轉(zhuǎn)換

  2.泛型的語(yǔ)法使用

  2.1 泛型在集合中的使用

  單列集合中List中

public interface List<E> extends Collection<E> {
----
<T> T[] toArray(T[] a);
----
}

  雙列集合Map中

public class HashMap<K,V> extends AbstractMap<K,V>
implements Map<K,V>, Cloneable, Serializable {
---
V get(Object key){---};
V put(K key, V value){---};
V remove(Object key){---};
void putAll(Map<? extends K, ? extends V> m){---};
-----
}

  小伙們可以看到:List,HashMap的源碼,在聲明集合時(shí)或者定義方法時(shí),使用采用尖括號(hào)內(nèi)加占位符的形式 ,這里的占位符就是我們上面說(shuō)的泛型標(biāo)記符,泛型標(biāo)記符號(hào)E,K,V,T等用來(lái)表示任意類型(E,K,V,T也就是“泛型形參”,在實(shí)例化集合對(duì)象時(shí)需要明確的具體的類型(也就是“泛型的實(shí)際參數(shù)”))。

  通過(guò)觀察集合的源碼,那么我們自己也可以定義泛型接口,泛型類以及泛型方法,下面我們一起操作一下吧。

  2.2 聲明泛型接口

  泛型應(yīng)用于接口。例如生成器(GeneratorType),這是一種專門負(fù)責(zé)創(chuàng)建對(duì)象的類。當(dāng)使用生成器創(chuàng)建新的對(duì)象時(shí),它不需要任何參數(shù),也就是說(shuō)生成器無(wú)需額外的信息就知道如何創(chuàng)建新對(duì)象。

  一般而言,一個(gè)生成器只定義一個(gè)方法,該方法用以產(chǎn)生新的對(duì)象。

/**
* 定義一個(gè)泛型接口:生成任意對(duì)象
* @param <T>: 泛型形式參數(shù),可以是任意類型
*/
public interface GeneratorType<T> {
T create();
}

/**
* 測(cè)試泛型接口
*/
class DemoGeneratorType{
public static void main(String[] args) {
//1.使用生成器:創(chuàng)建random對(duì)象
GeneratorType<Random> gt= new GeneratorType<Random>() {
@Override
public Random create() {
return new Random();
}
};
//2.使用 GeneratorType:創(chuàng)建對(duì)象
Random random = gt.create();
}
}

  來(lái),小伙伴們,我們一起分析下上面的代碼:

  我們聲明了一個(gè)泛型接口 GeneratorType,目的用來(lái)生成任意類型的對(duì)象,在這里T可以表示任意類型。

  我們?cè)跍y(cè)試類中,通過(guò)GeneratorType創(chuàng)建對(duì)象時(shí),可以傳遞任意類型。

  比如 GeneratorType,那么就可以生成Random對(duì)象了

  注意: 在這里,我們通過(guò)匿名內(nèi)部類的方式創(chuàng)建了Random對(duì)象,這種寫(xiě)法大家要慢慢熟悉喔。

  2.3 聲明泛型類

  泛型應(yīng)用于類上面。例如訂單類(Order),這是一個(gè)專門負(fù)責(zé)封裝訂單里面商品的類,當(dāng)我們購(gòu)物生成訂單時(shí),訂單里面可以包含任何商品信息。

  請(qǐng)注意,在類上定義的泛型,在類的變量、方法的參數(shù)以及方法中同樣也能使用(靜態(tài)方法除外)。

/**
* 定義一個(gè)訂單類:封裝任意類型的商品信息
* @param <T>
*/
public class Order<T> {
private T t ;//在變量中使用: T表示任意商品類型
public T get(){//在普通方法中使用:T表示任意商品類型
return t;
}
public void set(T t){//在方法的參數(shù)使用: T表示任意類型
this.t = t;
}
//測(cè)試:
public static void main(String[] args) {
Order<Phone> order = new Order<Phone>();//創(chuàng)建訂單對(duì)象:封裝Phone商品
order.set(new Phone("華為Mate20",3899.0));
System.out.println("商品名稱:"+order.get().getPhoneName());
}
}
//定義手機(jī)商品類
class Phone{
private String phoneName;
private Double phonePrice;

public Phone(String phoneName, Double phonePrice) {
this.phoneName = phoneName;
this.phonePrice = phonePrice;
}

public Phone() {
}

public String getPhoneName() {
return phoneName;
}

public void setPhoneName(String phoneName) {
this.phoneName = phoneName;
}

public Double getPhonePrice() {
return phonePrice;
}

public void setPhonePrice(Double phonePrice) {
this.phonePrice = phonePrice;
}
}

  ok,泛型類我們聲明完成了,大家看一下是不是和我們聲明泛型接口很相似啊,確實(shí)是一樣的。

  聲明的語(yǔ)法就是:類名,在這里T可以表示任意類型。

  小伙伴也可以看到,我們定義了一個(gè)帶泛型的Order類,在我們創(chuàng)建訂單對(duì)象時(shí),可以傳入任意類型的商品對(duì)象,使我們的操作更加靈活

  2.4 聲明泛型方法

  泛型應(yīng)用于方法上面。前面說(shuō)過(guò)在泛型類上定義的泛型,在類的方法中也能使用(靜態(tài)方法除外)。但是有的時(shí)候我們只想在某個(gè)方法上使用泛型,而不是整個(gè)類,這也是被允許的,下面我和小伙們一起來(lái)體驗(yàn)一下。

  比如FactoryBean工廠類,通過(guò)泛型方法,創(chuàng)建任意類型的對(duì)象。

package cn.qf;
/**
* 定義一個(gè)工廠Bean:
*/
public class FactoryBean {
/*
定義不帶泛型的方法
*/
public static Object createObject0(String className) throws Exception{
return Class.forName(className).newInstance();
}
/*
定義一個(gè)普通的泛型方法:className表示類的全路徑
*/
public <T> T createObject1(String className) throws Exception{
return (T) Class.forName(className).newInstance();
}
/*
定義一個(gè)靜態(tài)的泛型方法:className表示類的全路徑
*/
public static <T> T createObject2(String className)throws Exception{
return (E) Class.forName(className).newInstance();
}
//測(cè)試:
public static void main(String[] args) throws Exception {
//創(chuàng)建一個(gè)Phone對(duì)象 : 不使用泛型方法,需要類型強(qiáng)轉(zhuǎn)
Phone p1 = (Phone) FactoryBean.createObject0("cn.qf.Phone");
//創(chuàng)建一個(gè)Phone對(duì)象 :泛型方法,不需要類型強(qiáng)轉(zhuǎn)
Phone p2 = FactoryBean.createObject2("cn.qf.Phone");
}
}

class Phone{
private String phoneName;
private Double phonePrice;
----
}

  在這里我們使用工廠模式來(lái)創(chuàng)建對(duì)象,為了在我們獲取對(duì)象時(shí),不用類型強(qiáng)轉(zhuǎn),我們也使用了泛型。小伙伴通過(guò)代碼可以看到,不使用泛型的方法,在獲取對(duì)象時(shí),需要類型強(qiáng)轉(zhuǎn)(可能會(huì)引起類型強(qiáng)轉(zhuǎn)異常)。

  在使用泛型方法獲取對(duì)象時(shí),不需要類型強(qiáng)轉(zhuǎn)(可以避免引起類型強(qiáng)轉(zhuǎn)異常)。

  2.5 泛型方法、泛型接口、泛型類小結(jié)

  從上面的介紹小伙伴也看到了,泛型類的好處就是在泛型類上定義的泛型,在類的方法中也能使用(普通靜態(tài)方法除外)。而泛型方法的最大優(yōu)點(diǎn)就是能獨(dú)立于類,不受類是否是泛型類的限制。因此當(dāng)你考慮使用泛型的時(shí)候,優(yōu)先考慮定義泛型方法。如果非要定義泛型類,

  個(gè)人建議通過(guò)使用泛型方法來(lái)將整個(gè)類泛型化,因?yàn)檫@樣就不用擔(dān)心靜態(tài)方法的事,如果有靜態(tài)方法那必然是泛型方法。這樣就能避免普通靜態(tài)方法無(wú)法獲取泛型類泛型的尷尬局面。

  你以為這就把泛型介紹完了嗎?并沒(méi)有,小伙伴們先休息片刻,稍后我們繼續(xù)喔。

  闖關(guān)練習(xí)

  需求:

  定義一個(gè)泛型類:

  包含與類的泛型一樣的變量,

  包含與類的泛型一樣的方法,參數(shù)也使用泛型

  同時(shí)定義一個(gè)類的泛型不相同的泛型方法

  答案:

/**
* 定義泛型類:
* @param <T>: 泛型T
*/
public class GenericDemo4<T> {
//1.定義一個(gè)與T 一樣的變量
private T t;
//2.定義一個(gè)與T一樣的方法
public T test1(T outer){
System.out.println(outer);
return outer;
}
//3.定義一個(gè)與T不一樣的方法
public <E> E test2(E e){
System.out.println("自定義泛型的方法:"+e);
return e;
}
//測(cè)試:
public static void main(String[] args) {
//1.創(chuàng)建對(duì)象:指定T的泛型為 String
GenericDemo4<String> gt = new GenericDemo4<String>();
//2.調(diào)用 與T 一樣的泛型方法
gt.test1("hello world");
//3.調(diào)用 與T 不一樣的泛型方法
gt.test2(10);
}
}

好程序員公眾號(hào)

  • · 剖析行業(yè)發(fā)展趨勢(shì)
  • · 匯聚企業(yè)項(xiàng)目源碼

好程序員開(kāi)班動(dòng)態(tài)

More+
IT培訓(xùn)IT培訓(xùn)
在線咨詢
IT培訓(xùn)IT培訓(xùn)
試聽(tīng)
IT培訓(xùn)IT培訓(xùn)
入學(xué)教程
IT培訓(xùn)IT培訓(xùn)
立即報(bào)名
IT培訓(xùn)

Copyright 2011-2023 北京千鋒互聯(lián)科技有限公司 .All Right 京ICP備12003911號(hào)-5 京公網(wǎng)安備 11010802035720號(hào)

中文在线免费看视频_国产成人精品亚洲日本在线观看_亚洲精品第一综合99久久_国产亚洲精品日韩综合网

            亚洲色图欧美在线| 日韩欧美你懂的| 天堂va蜜桃一区二区三区漫画版| 在线综合亚洲欧美在线视频| 国产麻豆午夜三级精品| 亚洲视频免费观看| 欧美高清视频在线高清观看mv色露露十八| 日韩专区一卡二卡| 欧美国产精品一区二区三区| 欧美色中文字幕| 国产麻豆视频精品| 一级特黄大欧美久久久| 日韩美女视频在线| 一本到三区不卡视频| 久久成人免费网站| 亚洲欧美偷拍三级| 欧美变态tickling挠脚心| 色综合久久88色综合天天免费| 久久99精品一区二区三区| 亚洲精品五月天| 久久精品视频网| 91精品国产福利| 日本高清不卡视频| 成人高清免费观看| 狠狠网亚洲精品| 亚洲福利视频导航| 中文字幕在线观看一区| 久久天堂av综合合色蜜桃网| 欧美色电影在线| 91亚洲国产成人精品一区二三 | 99精品国产视频| 免费在线观看成人| 亚洲国产欧美在线| 亚洲欧洲www| 国产午夜精品一区二区三区视频 | 欧美色视频在线| 欧美国产1区2区| 色偷偷久久人人79超碰人人澡| 亚洲乱码国产乱码精品精小说| 99re热视频精品| 午夜视频久久久久久| 亚洲色图在线播放| 国产精品对白交换视频| 91蜜桃婷婷狠狠久久综合9色| 国产亚洲综合在线| 欧洲av在线精品| 狠狠狠色丁香婷婷综合久久五月| 国产精品灌醉下药二区| 91精品国产丝袜白色高跟鞋| 国产69精品一区二区亚洲孕妇| 中文字幕亚洲电影| 日韩欧美美女一区二区三区| 白白色亚洲国产精品| 婷婷久久综合九色国产成人| 国产三级欧美三级日产三级99 | 精品一区二区综合| 亚洲四区在线观看| 精品国产在天天线2019| 色综合久久久久综合体| 欧美a级一区二区| 一区二区三区在线观看视频| 亚洲精品视频观看| 亚洲午夜国产一区99re久久| 亚洲福利视频三区| 日本不卡1234视频| 久久成人av少妇免费| 狠狠色2019综合网| 福利视频网站一区二区三区| 成人免费黄色大片| 色婷婷国产精品综合在线观看| 91国产福利在线| 3d动漫精品啪啪一区二区竹菊| 日韩一区二区免费在线电影| 欧美精品视频www在线观看| 毛片一区二区三区| 亚洲第一在线综合网站| 亚洲欧洲三级电影| 久久久精品国产免大香伊| 91精品国产91综合久久蜜臀| 在线免费不卡电影| 99视频一区二区| 成人毛片老司机大片| 国产成人一区在线| 久久99久久精品欧美| 日韩国产成人精品| 午夜久久久久久| 亚洲国产一区二区三区| 亚洲欧美激情一区二区| 日本一区二区三区高清不卡| 精品国产91乱码一区二区三区 | 中文欧美字幕免费| 久久欧美一区二区| 久久五月婷婷丁香社区| 精品国产免费一区二区三区香蕉| 91精品国产高清一区二区三区| 欧美综合一区二区三区| 色久综合一二码| 91极品美女在线| 在线观看中文字幕不卡| 日本韩国精品在线| 欧美日韩一区二区三区在线| 欧美三级电影在线看| 欧美在线免费观看视频| 欧美午夜精品一区二区三区| 91国产福利在线| 欧美视频中文一区二区三区在线观看| 91视视频在线观看入口直接观看www | 午夜视频一区二区三区| 午夜精品福利在线| 亚洲福利一二三区| 日韩二区三区在线观看| 91亚洲男人天堂| 久久综合色鬼综合色| 午夜久久福利影院| 91视频在线观看| 久久婷婷一区二区三区| 国产亚洲精品久| 日韩一级高清毛片| 久久久不卡影院| 中文字幕一区二区三区不卡在线| 亚洲裸体xxx| 日韩精品欧美精品| 国产乱人伦偷精品视频不卡 | 亚洲伦在线观看| 日韩va欧美va亚洲va久久| 久久99精品一区二区三区三区| 欧美唯美清纯偷拍| 亚洲欧美韩国综合色| 成人做爰69片免费看网站| 国产精品自产自拍| 色狠狠综合天天综合综合| 337p亚洲精品色噜噜| 国产亚洲精品久| 亚洲一区二区免费视频| 亚洲777理论| 在线看一区二区| 亚洲视频在线一区| eeuss鲁一区二区三区| 91蝌蚪porny九色| 精品视频在线看| 欧美激情自拍偷拍| 亚洲一区二区偷拍精品| 国产乱色国产精品免费视频| 欧美主播一区二区三区| 久久嫩草精品久久久精品| 亚洲午夜激情av| 不卡的av中国片| 日韩精品一区二区三区四区| 专区另类欧美日韩| 国产精品一二一区| 日韩欧美在线一区二区三区| 亚洲欧美国产三级| 粉嫩13p一区二区三区| 欧美一级日韩不卡播放免费| 亚洲精品一二三| 从欧美一区二区三区| 日韩欧美你懂的| 亚洲第一福利视频在线| 不卡区在线中文字幕| 久久久久久久综合色一本| 视频一区在线播放| 欧美伊人久久久久久午夜久久久久| 国产欧美久久久精品影院| 经典三级一区二区| 国产精品欧美经典| 欧美伊人久久久久久午夜久久久久| 亚洲第一在线综合网站| 日韩免费视频一区| 综合色天天鬼久久鬼色| 国产传媒久久文化传媒| 精品免费一区二区三区| 轻轻草成人在线| 欧美裸体bbwbbwbbw| 亚洲综合免费观看高清完整版| www.欧美日韩| 国产精品福利影院| eeuss影院一区二区三区| 中文字幕欧美区| 国产精品1024| 国产女主播在线一区二区| 国内久久精品视频| 精品人伦一区二区色婷婷| 久久99日本精品| 精品成人在线观看| 国产精品综合二区| 国产精品情趣视频| 91视频在线看| 亚洲国产成人porn| 69堂成人精品免费视频| 日本色综合中文字幕| 日韩视频永久免费| 国产福利电影一区二区三区| 久久久美女毛片| 粉嫩嫩av羞羞动漫久久久| 中文字幕一区在线观看视频| 色哟哟国产精品免费观看| 亚洲成a人v欧美综合天堂 | 国产精品国产成人国产三级| 成人福利视频在线看| 又紧又大又爽精品一区二区|