全文大約【6000】字,不說(shuō)廢話(huà),只講可以讓你學(xué)到技術(shù)、明白原理的純干貨!本文帶有豐富的案例及配圖視頻,讓你更好地理解和運(yùn)用文中的技術(shù)概念,并可以給你帶來(lái)具有足夠啟迪的思考......
一. 泛型簡(jiǎn)介
作為Java中常用且重要的一個(gè)概念,泛型幫我們實(shí)現(xiàn)了代碼重用,也保證了類(lèi)型安全。但關(guān)于它的詳細(xì)內(nèi)容,目前很多同學(xué)還不清楚,所以接下來(lái)小編就帶各位來(lái)學(xué)習(xí)這個(gè)重要的知識(shí)點(diǎn)。
1.背景
為了能夠讓大家更好地理解泛型的作用,在我們開(kāi)始學(xué)習(xí)泛型之前,小編先給大家提個(gè)開(kāi)發(fā)需求:
我們現(xiàn)在有一個(gè)需求,要求你編寫(xiě)一個(gè)對(duì)數(shù)組進(jìn)行排序的方法,該方法能夠?qū)Ω↑c(diǎn)型數(shù)組、整型數(shù)組、字符串?dāng)?shù)組或者是其他任何類(lèi)型的數(shù)組進(jìn)行排序,你該如何實(shí)現(xiàn)?
有的小伙伴會(huì)說(shuō),這很簡(jiǎn)單啊,我可以利用方法重載,針對(duì)每種類(lèi)型的數(shù)組分別編寫(xiě)一個(gè)排序方法,需要為幾種類(lèi)型的數(shù)組排序,我就定義幾個(gè)排序方法。如果你是這么實(shí)現(xiàn)的,小編只能哈哈哈了,這種做法明顯不好,代碼可重用性太差。
又有的小伙伴說(shuō)了,可以定義一個(gè)方法,里面設(shè)置一個(gè)Object[]類(lèi)型的參數(shù),這樣無(wú)論是哪種類(lèi)型都可以處理了。這樣定義方法,比上面那個(gè)同學(xué)的想法要稍好一點(diǎn),但此時(shí)我們需要在Object類(lèi)型和整型、String類(lèi)型或其他類(lèi)型之間進(jìn)行強(qiáng)制類(lèi)型轉(zhuǎn)換。所以這樣做就無(wú)法保證集合中元素的類(lèi)型安全,稍一不慎就可能會(huì)導(dǎo)致ClassCastException類(lèi)型轉(zhuǎn)換異常。
so,這也不行,那也不行,到底該怎么辦?這不,為了解決這些問(wèn)題,所以Java中就產(chǎn)生了泛型這個(gè)技術(shù)。
2.概念
泛型(generics)這個(gè)技術(shù)是在JDK 5中引入的新特性,它的本質(zhì)其實(shí)是類(lèi)型參數(shù)化,利用泛型可以實(shí)現(xiàn)一套代碼對(duì)多種數(shù)據(jù)類(lèi)型的動(dòng)態(tài)處理,保證了更好的代碼重用性。并且泛型還提供了編譯時(shí)對(duì)類(lèi)型安全進(jìn)行檢測(cè)的機(jī)制,該機(jī)制允許我們?cè)诰幾g時(shí)就能夠檢測(cè)出非法的類(lèi)型,提高了代碼的安全性。
這種特性,使得泛型成了一種“代碼模板”,讓我們利用一套代碼就能實(shí)現(xiàn)對(duì)各種類(lèi)型的套用。也就是說(shuō),我們只需要編寫(xiě)一次代碼,就可以實(shí)現(xiàn)萬(wàn)能匹配,這也是”泛型“這個(gè)概念的含義,你可以將其理解為”廣泛的類(lèi)型“、”非特定的類(lèi)型“。咱們上面的那個(gè)需求,利用泛型就能輕松實(shí)現(xiàn),還不需要進(jìn)行類(lèi)型的強(qiáng)制轉(zhuǎn)換,并且也保證了數(shù)據(jù)的類(lèi)型安全。
3.作用
所以根據(jù)上面泛型的概念,我們可以提取出泛型的核心作用:
● 泛型可以在編譯時(shí)對(duì)類(lèi)型進(jìn)行安全檢測(cè),使得所有的強(qiáng)制轉(zhuǎn)換都是自動(dòng)隱式實(shí)現(xiàn)的,保證了類(lèi)型的安全性;
● 泛型作為”代碼模板“,實(shí)現(xiàn)了一套代碼對(duì)各種類(lèi)型的套用,提高了代碼的可重用性。
4.使用場(chǎng)景
基于泛型的這些特性和作用,我們可以把泛型用在很多地方,小編在這里給大家做了一個(gè)總結(jié),通常情況下,泛型可以用在如下場(chǎng)景中:
● 泛型集合:在各種集合中使用泛型,保證集合中元素的類(lèi)型安全;
● 泛型方法:在各種方法中使用泛型,保證方法中參數(shù)的類(lèi)型安全;
● 泛型類(lèi):在類(lèi)的定義時(shí)使用泛型,為某些變量和方法定義通用的類(lèi)型;
● 泛型接口:在接口定義時(shí)使用泛型,為某些常量和方法定義通用的類(lèi)型;
● 泛型加反射:泛型也可以結(jié)合反射技術(shù),實(shí)現(xiàn)在運(yùn)行時(shí)獲取傳入的實(shí)際參數(shù)等功能。
但是我們要注意,無(wú)論我們?cè)谀膫€(gè)地方使用泛型,泛型都不能是基本類(lèi)型,關(guān)于這一點(diǎn),我會(huì)在講解泛型擦除時(shí)再細(xì)說(shuō)。
總之,泛型的應(yīng)用場(chǎng)景有很多,以上只是小編給大家總結(jié)的幾個(gè)重點(diǎn)使用場(chǎng)景,接下來(lái)小編就這幾個(gè)場(chǎng)景分別給大家進(jìn)行講解。
二. 泛型集合
1.簡(jiǎn)介
泛型最常見(jiàn)的一個(gè)用途,就是在集合中對(duì)數(shù)據(jù)元素的類(lèi)型進(jìn)行限定。集合作為一個(gè)容器,主要是用來(lái)容納保存數(shù)據(jù)元素的,但集合的設(shè)計(jì)者并不知道我們會(huì)用集合來(lái)保存什么類(lèi)型的對(duì)象,所以他們就把集合設(shè)計(jì)成能保存任何類(lèi)型的對(duì)象。這就要求集合具有很好的通用性,內(nèi)部可以裝載各種類(lèi)型的數(shù)據(jù)元素。集合之所以可以實(shí)現(xiàn)這一功能,主要是集合的源碼中已經(jīng)結(jié)合泛型做了相關(guān)的設(shè)計(jì),我們來(lái)看看Collection的源碼,如下圖所示:
而Collection的子類(lèi)List中也增加了對(duì)泛型的支持,如下圖所示:
上面的源碼中,集合中的就是泛型,至于泛型的名字為什么叫做”E“,后面小編再跟大家細(xì)說(shuō)。但不管如何,從這些源碼中我們就可以看出,Java的集合本身就支持泛型了。我們先不管集合底層是如何設(shè)計(jì)的,咱們先從基本用法開(kāi)始學(xué)起。
2. 語(yǔ)法
在集合中使用泛型其實(shí)比較簡(jiǎn)單,我們以List集合為例,其基本語(yǔ)法如下:
//可以省略后面ArrayList里的String,編譯器可以自動(dòng)根據(jù)前面<>里的類(lèi)型,推斷出后面<>里使用的泛型類(lèi)型
List<String> list = new ArrayList<>();
上面的語(yǔ)法,其含義是說(shuō)我們定義了一個(gè)ArrayList集合,但該集合不能隨便添加數(shù)據(jù)元素,只能添加String類(lèi)型的元素。也就是說(shuō),在上面的語(yǔ)法中,我們通過(guò)泛型,限定了ArrayList集合的元素類(lèi)型。當(dāng)我們定義List集合時(shí),如果已經(jīng)限定了泛型類(lèi)型,但后面添加元素時(shí)你非得違背這個(gè)類(lèi)型,Java就會(huì)在編譯階段報(bào)錯(cuò),如下圖所示:
我們?cè)诙x集合時(shí),可以省略后面ArrayList里的String,編譯器可以自動(dòng)根據(jù)前面<>里的類(lèi)型,推斷出后面<>里使用的泛型類(lèi)型。另外Set和Map集合的用法,與List集合類(lèi)似,我們可以通過(guò)下面這個(gè)案例來(lái)體會(huì)一下集合泛型的魅力。
3. 代碼案例
在本案例中,我們可以給List、Set、Map等集合設(shè)置泛型,從而限定集合中數(shù)據(jù)元素的類(lèi)型。
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* @author 一一哥Sun
*/
public class Demo01 {
public static void main(String[] args) {
//定義集合泛型
//此時(shí)的集合只能接受String類(lèi)型元素,后面ArrayList<>中的<>,里面的String可寫(xiě)可不寫(xiě)
List<String> list = new ArrayList<>();
//如果類(lèi)型不一致,在編譯階段就會(huì)檢測(cè)出有錯(cuò)誤,保證了數(shù)據(jù)的安全性
//list.add(100);
list.add("Hello");
String strValue = list.get(0);
System.out.println("list value="+strValue);
Set<Integer> set=new HashSet<>();
//set.add("hello");
set.add(200);
Iterator<Integer> iterator = set.iterator();
while(iterator.hasNext()) {
Integer nextValue = iterator.next();
System.out.println("set value="+nextValue);
}
//限定Map集合的key是String類(lèi)型,value是Long類(lèi)型
Map<String,Long> map=new HashMap<>();
//map.put("number", "10000");
map.put("number", 10000L);
Long value = map.get("number");
System.out.println("map value="+value);
}
}
在這個(gè)案例中,我們?cè)诩现型ㄟ^(guò)泛型限定了集合元素的數(shù)據(jù)類(lèi)型。如果元素的類(lèi)型與要求的不一致,在編譯階段就會(huì)檢測(cè)出有錯(cuò)誤,不需要進(jìn)入到運(yùn)行階段才能發(fā)現(xiàn)類(lèi)型不一致。而且我們?cè)讷@取集合中的元素時(shí),也不需要進(jìn)行強(qiáng)制類(lèi)型轉(zhuǎn)換,程序會(huì)自動(dòng)進(jìn)行隱式轉(zhuǎn)換,這就保證了數(shù)據(jù)的安全性,也提高了代碼的執(zhí)行效率。
另外我們所使用的泛型參數(shù),也被稱(chēng)為類(lèi)型變量,是用于指定泛型類(lèi)型名稱(chēng)的標(biāo)識(shí)符。我們可以根據(jù)需要,在集合、類(lèi)、接口、方法等地方定義一個(gè)或多個(gè)泛型參數(shù),這些泛型化的類(lèi)型參數(shù)也被稱(chēng)為參數(shù)化的類(lèi)或參數(shù)化的類(lèi)型。
三. 泛型接口
我們除了可以在集合中使用泛型,還可以在定義接口時(shí)使用泛型,這也是泛型的常用形式之一。
1.語(yǔ)法
在定義接口時(shí)使用泛型的基本語(yǔ)法格式如下:
//在接口名稱(chēng)后面緊跟泛型<>
public interface InterfaceName<T> {
// 接口的方法定義
}
//可以同時(shí)定義多個(gè)泛型,多個(gè)泛型用","逗號(hào)分割
public interface InterfaceName2<M,N> {
// 接口的方法定義
}
大家注意,這里泛型的名稱(chēng)T/M/N,其實(shí)是我們隨意寫(xiě)的,我們并不一定非要使用T,也可以使用M、N、E等任意名稱(chēng)。而之所以使用T,只是采用了Type類(lèi)型這個(gè)單詞的首字母而已。雖然如此,但我們?cè)趯?shí)際開(kāi)發(fā)時(shí),為了盡量做到見(jiàn)名知意,請(qǐng)大家還是要盡量采用有意義的名稱(chēng),通常會(huì)使用如下幾個(gè)常用字母:
● E - Element(表示集合元素,常在集合中使用);
● T - Type(表示Java類(lèi),常用在類(lèi)和接口中);
● K - Key(表示鍵);
● V - Value(表示值);
● N - Number(表示數(shù)值類(lèi)型);
● ? - 表示不確定的Java類(lèi)型。
另外,這里的T只是一種類(lèi)型參數(shù),你可以把它理解成是一個(gè)”表面的占位符“。在真正賦值時(shí),它可以用任何實(shí)際的類(lèi)型來(lái)替代,如Integer、String、自定義類(lèi)型等。并且我們?cè)诙x接口時(shí),可以根據(jù)實(shí)際需要,同時(shí)定義多個(gè)泛型,多個(gè)泛型之間用","逗號(hào)分割。而在實(shí)際使用時(shí),我們需要在該接口名的后面加上一對(duì)尖括號(hào),用來(lái)傳入實(shí)際的類(lèi)型。
2. 代碼案例
2.1 定義泛型接口
接下來(lái)我們?cè)偻ㄟ^(guò)一個(gè)案例來(lái)學(xué)習(xí)一下接口泛型如何使用,這里我們定義一個(gè)泛型接口ICompute,內(nèi)部定義了一個(gè)用于計(jì)算的方法,如下所示:
/**
* 定義一個(gè)用于計(jì)算的接口
*/
public interface ICompute<M,N> {
//定義一個(gè)加法計(jì)算的方法
M add(M m,N n);
}
2.2 實(shí)現(xiàn)泛型接口
接下來(lái)我們把這個(gè)接口進(jìn)行實(shí)現(xiàn),代碼如下:
public class Demo02 {
public static void main(String[] args) {
//這里壹哥直接利用匿名內(nèi)部類(lèi)的寫(xiě)法進(jìn)行實(shí)現(xiàn),大家也可以編寫(xiě)一個(gè)類(lèi)實(shí)現(xiàn)ICompute接口
//我這里傳入了兩個(gè)Integer類(lèi)型的具體參數(shù),分別取代M和N
ICompute<Integer, Integer> iCompute = new ICompute<Integer, Integer>() {
@Override
public Integer add(Integer m, Integer n) {
return m+n;
}
};
//調(diào)用上面實(shí)現(xiàn)的方法
Integer result = iCompute.add(100, 200);
System.out.println("result="+result);
}
}
這里小編直接利用匿名內(nèi)部類(lèi)的寫(xiě)法進(jìn)行實(shí)現(xiàn),大家也可以編寫(xiě)一個(gè)類(lèi)實(shí)現(xiàn)ICompute接口。我這里傳入了兩個(gè)Integer類(lèi)型的具體參數(shù),分別取代M和N,當(dāng)然我們也可以根據(jù)需要,在實(shí)現(xiàn)時(shí)傳入Float/Double等其他類(lèi)型。
四. 泛型類(lèi)
其實(shí)Java的類(lèi)和接口在很多地方都很類(lèi)似,所以我們?cè)诙x接口時(shí)可以使用泛型,也可以在定義類(lèi)時(shí)使用泛型,泛型類(lèi)常用于類(lèi)中的屬性類(lèi)型不確定的情況下,這也是泛型的常用形式之一。
1.語(yǔ)法
其實(shí)泛型類(lèi)的聲明和普通類(lèi)的聲明類(lèi)似,只是在類(lèi)名后面多添加了一個(gè)關(guān)于泛型的聲明。并且泛型類(lèi)的類(lèi)型參數(shù)部分,可以包含一個(gè)或多個(gè)類(lèi)型參數(shù),多個(gè)參數(shù)間用逗號(hào)隔開(kāi)。一般我們?cè)诙x泛型類(lèi)時(shí),需要在類(lèi)名后添加類(lèi)型參數(shù),語(yǔ)法格式與泛型接口一致,如下所示:
public class ClassName<T> {
// 類(lèi)的成員變量和方法定義
}
泛型類(lèi)的要求和泛型接口完全一樣,這里小編就不再贅述了。
2. 代碼案例
2.1 定義泛型類(lèi)
接下來(lái)小編定義一個(gè)泛型類(lèi)Pair,它包含兩個(gè)類(lèi)型相同的成員變量:
public class Pair<T> {
//我們可以直接把泛型當(dāng)成一個(gè)java的“類(lèi)型”來(lái)用,Java類(lèi)怎么用,泛型就可以怎么用
//直接利用泛型來(lái)定義成員變量
private T first;
private T second;
//構(gòu)造方法中使用泛型
public Pair(T first, T second) {
this.first = first;
this.second = second;
}
//方法中使用泛型
public T getFirst() {
return first;
}
public T getSecond() {
return second;
}
}
在上述代碼中,我們定義了一個(gè)泛型類(lèi)Pair,它有兩個(gè)類(lèi)型相同的成員變量first和second,以及一個(gè)構(gòu)造函數(shù)和兩個(gè)訪問(wèn)成員變量的方法。在定義Pair類(lèi)時(shí),我們使用了類(lèi)型參數(shù)T來(lái)代表類(lèi)型,而在實(shí)例化該泛型類(lèi)時(shí),需要指明泛型類(lèi)中的類(lèi)型參數(shù),并賦予泛型類(lèi)屬性相應(yīng)類(lèi)型的值,比如指定T是String/Integer/Student/Person等任意類(lèi)型。
2.2 使用泛型類(lèi)
接下來(lái)是使用Pair類(lèi)的具體代碼:
public class Demo03 {
public static void main(String[] args) {
//調(diào)用泛型類(lèi)
Pair<String> pair = new Pair<>("Hello", "World");
// 輸出 "Hello"
System.out.println("first="+pair.getFirst());
// 輸出 "World"
System.out.println("last="+pair.getSecond());
}
}
在上述代碼中,我們使用了Pair類(lèi),并將類(lèi)型參數(shù)指定為String類(lèi)型。然后我們創(chuàng)建了一個(gè)Pair對(duì)象,并通過(guò)getFirst和getSecond方法訪問(wèn)了成員變量。
五. 繼承泛型類(lèi)和實(shí)現(xiàn)泛型接口
在Java中,泛型不僅可以用于類(lèi)、方法的定義,還可以用于類(lèi)和接口的繼承與實(shí)現(xiàn)。接下來(lái)小編就給大家詳細(xì)介紹一下,該如何繼承泛型類(lèi)和實(shí)現(xiàn)泛型接口。
1.簡(jiǎn)介
大家要注意,一個(gè)被定義為泛型的類(lèi)和接口,也可以被子類(lèi)繼承和實(shí)現(xiàn)。例如下面的示例代碼,就給大家演示了如何繼承一個(gè)泛型類(lèi)。
public class FatherClass<T1>{}
public class SonClass<T1,T2,T3> extents FatherClass<T1>{}
但是如果我們想要SonClass類(lèi)在繼承FatherClass類(lèi)時(shí),能夠保留父類(lèi)的泛型類(lèi)型,則需要在繼承時(shí)就指定。否則直接使用extends FatherClass語(yǔ)句進(jìn)行繼承操作時(shí),T1、T2 和 T3都會(huì)自動(dòng)變?yōu)镺bject類(lèi)型,所以一般情況下都是將父類(lèi)的泛型類(lèi)型保留。
接下來(lái)小編會(huì)分別給大家介紹一下如何繼承泛型類(lèi)和實(shí)現(xiàn)泛型接口。
2. 繼承泛型類(lèi)
2.1 定義泛型父類(lèi)
在Java中,我們可以通過(guò)繼承一個(gè)泛型類(lèi)來(lái)實(shí)現(xiàn)泛型的重用。子類(lèi)可以繼承父類(lèi)中定義的泛型類(lèi)型,并根據(jù)自己的需要,增加、修改泛型類(lèi)型的參數(shù),從而實(shí)現(xiàn)泛型類(lèi)的個(gè)性化定制。下面是一個(gè)泛型類(lèi)的示例:
/**
* 泛型類(lèi)
*/
public class GenericClass<T1> {
private T1 data;
public GenericClass(T1 data) {
this.data = data;
}
public T1 getData() {
return data;
}
}
2.2 泛型子類(lèi)繼承父類(lèi)
我們可以通過(guò)繼承GenericClass類(lèi),來(lái)創(chuàng)建一個(gè)新的泛型類(lèi)SonGenericClass,并增加新的泛型類(lèi)型:
/**
* 泛型類(lèi)
*/
public class SonGenericClass<T1,T2> extends GenericClass<T1>{
private T2 otherData;
public SonGenericClass(T1 data, T2 otherData) {
super(data);
this.otherData = otherData;
}
public T2 getOtherData() {
return otherData;
}
}
在上面的示例中,SonGenericClass類(lèi)繼承了GenericClass類(lèi),并增加了一個(gè)新的泛型類(lèi)型T2。在構(gòu)造方法中,調(diào)用父類(lèi)的構(gòu)造方法,并傳入T1類(lèi)型的數(shù)據(jù),然后再將T2類(lèi)型的數(shù)據(jù)賦值給類(lèi)的成員變量otherData。通過(guò)這種方式,我們可以創(chuàng)建一個(gè)具有更多泛型參數(shù)的類(lèi),并且保留了原始泛型類(lèi)的特性。我們來(lái)看看最終的測(cè)試結(jié)果:
public class Demo08 {
public static void main(String[] args) {
SonGenericClass<Integer,String> son=new SonGenericClass<>(100, "hello");
//子類(lèi)從父類(lèi)中繼承來(lái)的泛型
Integer data = son.getData();
String otherData = son.getOtherData();
System.out.println("t1---data="+data+",t2---data="+otherData);
}
}
這樣,子類(lèi)通過(guò)繼承父類(lèi),也自動(dòng)獲得了父類(lèi)中的泛型。
3. 實(shí)現(xiàn)泛型接口
3.1 定義泛型接口
類(lèi)似于繼承泛型類(lèi),我們也可以通過(guò)實(shí)現(xiàn)泛型接口,來(lái)定義具有多個(gè)泛型參數(shù)的接口。實(shí)現(xiàn)泛型接口的過(guò)程與實(shí)現(xiàn)普通接口的過(guò)程相同,我們只需要在接口名后面添加這樣的泛型參數(shù)聲明即可。下面是一個(gè)泛型接口的示例:
/**
*
* 定義泛型接口
*/
public interface GenericInterface<T1> {
public void doSomething(T1 data);
}
3.2 兩種實(shí)現(xiàn)方式
我們?cè)趯?shí)現(xiàn)泛型接口時(shí),可以采用兩種實(shí)現(xiàn)方式:
指定具體類(lèi)型:就是在實(shí)現(xiàn)接口時(shí),明確指定泛型參數(shù)的具體類(lèi)型;
保留泛型參數(shù):在實(shí)現(xiàn)接口時(shí),不明確指定泛型參數(shù)的具體類(lèi)型,而是保留泛型參數(shù)。
如果是通過(guò)指定具體類(lèi)型的方式進(jìn)行實(shí)現(xiàn),一般形式如下:
public class StringPair implements Pair<String> {
.....
}
在這種方式中,我們定義了一個(gè)Pair接口,然后讓子類(lèi)StringPair進(jìn)行實(shí)現(xiàn),但在實(shí)現(xiàn)時(shí)就明確指定了具體的泛型參數(shù)為String。這樣,我們?cè)谑褂肧tringPair對(duì)象時(shí),就明確知道了類(lèi)內(nèi)部的數(shù)據(jù)類(lèi)型。
如果是通過(guò)保留泛型參數(shù)的方式進(jìn)行實(shí)現(xiàn),一般形式如下:
public class NumberPair<T extends 父類(lèi)型> implements Pair<T> {
......
}
在這種方式中,我們定義了一個(gè)泛型接口Pair,然后定義一個(gè)實(shí)現(xiàn)字類(lèi)NumberPair,可以在實(shí)現(xiàn)時(shí)保留泛型參數(shù)。
3.3 實(shí)現(xiàn)泛型接口
接下來(lái),我們?cè)倬帉?xiě)一個(gè)SubGenericInterface類(lèi),并通過(guò)保留泛型參數(shù)的方式,來(lái)實(shí)現(xiàn)GenericInterface接口,并增加一個(gè)新的泛型類(lèi)型T2,代碼如下:
public class SubGenericClass<T1,T2> implements GenericInterface<T1>{
private T2 otherData;
@Override
public void doSomething(T1 data) {
System.out.println("t1="+data);
}
public SubGenericClass(T2 otherData) {
this.otherData = otherData;
}
public T2 getOtherData() {
return otherData;
}
}
這樣泛型子類(lèi)就實(shí)現(xiàn)了泛型父類(lèi),并在子類(lèi)中增加了一個(gè)新的泛型,最終的結(jié)果如下所示:
public class Demo09 {
public static void main(String[] args) {
SubGenericClass<Integer,String> sub=new SubGenericClass<>("hello");
sub.doSomething(100);
String otherData = sub.getOtherData();
System.out.println("t2---data="+otherData);
}
}
其實(shí),實(shí)現(xiàn)泛型接口和繼承泛型類(lèi)都很簡(jiǎn)單,我們只需要在類(lèi)定義中使用相同的泛型類(lèi)型參數(shù),然后實(shí)現(xiàn)接口的方法或覆蓋超類(lèi)的方法即可。
以上就是關(guān)于泛型的概念、作用、泛型接口、泛型類(lèi)等相關(guān)的內(nèi)容,其實(shí)泛型的內(nèi)容還有很多,比如泛型方法、泛型擦除和泛型中的通配符等。但受限于篇幅,小編會(huì)在下一篇文章中繼續(xù)給大家講解這些內(nèi)容,敬請(qǐng)繼續(xù)關(guān)注哦。
五. 結(jié)語(yǔ)
至此,在本文中小編就把泛型的概念、作用、泛型接口和泛型類(lèi)給大家介紹完了,本文重點(diǎn)內(nèi)容如下:
● 泛型是一種類(lèi)型參數(shù),可以編寫(xiě)模板代碼來(lái)適應(yīng)任意類(lèi)型;
● 泛型在使用時(shí)不必對(duì)類(lèi)型進(jìn)行強(qiáng)制轉(zhuǎn)換,它可以通過(guò)編譯器在編譯階段對(duì)類(lèi)型進(jìn)行檢查;
● 使用泛型時(shí)可以把泛型參數(shù)替換成想要的class類(lèi)型,例如ArrayList,ArrayList等;
● 編譯器可以根據(jù)前面的泛型,在后面自動(dòng)推斷出類(lèi)型,例如List list = new ArrayList<>();
● 如果我們?cè)谑褂脮r(shí)不指定泛型參數(shù)類(lèi)型時(shí),編譯器會(huì)給出警告,且只能將視為Object類(lèi)型;
● 我們可以在接口和類(lèi)中定義泛型類(lèi)型,實(shí)現(xiàn)此接口的類(lèi)必須傳入正確的泛型類(lèi)型;
● 我們可以同時(shí)定義多個(gè)泛型,例如Map;
● 可以繼承泛型類(lèi)和實(shí)現(xiàn)泛型接口。