麻豆黑色丝袜jk制服福利网站-麻豆精品传媒视频观看-麻豆精品传媒一二三区在线视频-麻豆精选传媒4区2021-在线视频99-在线视频a

千鋒教育-做有情懷、有良心、有品質(zhì)的職業(yè)教育機構(gòu)

手機站
千鋒教育

千鋒學(xué)習(xí)站 | 隨時隨地免費學(xué)

千鋒教育

掃一掃進入千鋒手機站

領(lǐng)取全套視頻
千鋒教育

關(guān)注千鋒學(xué)習(xí)站小程序
隨時隨地免費學(xué)習(xí)課程

當(dāng)前位置:首頁  >  技術(shù)干貨  > Java之泛型基本使用

Java之泛型基本使用

來源:千鋒教育
發(fā)布人:zyh
時間: 2023-06-12 15:14:00 1686554040

  全文大約【4600】字,不說廢話,只講可以讓你學(xué)到技術(shù)、明白原理的純干貨!本文帶有豐富的案例及配圖視頻,讓你更好地理解和運用文中的技術(shù)概念,并可以給你帶來具有足夠啟迪的思考......

Java之泛型基本使用

  一. 泛型方法

  1.簡介

  我們可以在定義接口和類時使用泛型,這樣該接口和類中的所有方法及成員變量等處,也都可以使用該泛型。但其實泛型可以應(yīng)用在整個類上,也可以只應(yīng)用在類中的某個方法上。也就是說,方法所在的類可以是泛型類,也可以不是泛型類。方法中是否帶有泛型,與其所在的類有沒有泛型沒有關(guān)系。

  泛型方法是在調(diào)用方法時才確定類型的方法,泛型可以使得該方法獨立于類而產(chǎn)生變化。另外,static靜態(tài)方法無法訪問泛型類的類型參數(shù),因此,如果想讓一個static方法具有泛型能力,就必須使該靜態(tài)方法成為泛型方法。

  2.語法

  我們在定義泛型方法時,需要在方法名的前面添加類型參數(shù)。定義泛型方法的語法格式如下: 

[訪問權(quán)限修飾符] [static] [final] <類型參數(shù)列表> 返回值類型 方法名([形式參數(shù)列表])

  例如:  

public static <T> List showInfo(Class<T> clazz,int userId){}

  一般情況下,我們編寫泛型方法時,必須在該方法的名稱前聲明要使用的泛型,并且可以同時聲明多個泛型,中間也是用逗號分割。接下來小編就定義一個泛型方法,給大家具體介紹一下泛型方法的創(chuàng)建和使用。

  3. 代碼案例

  這里我們定義一個泛型方法,用于對數(shù)組排序后再遍歷元素輸出,代碼如下:  

import java.util.Arrays;

/**
* @author 一一哥Sun
*/
public class Demo04 {

//定義了一個靜態(tài)的泛型方法,遍歷數(shù)組中的每個元素
public static <T> void printArray(T[] arr) {
//先對數(shù)組進行排序
Arrays.sort(arr);
//再遍歷數(shù)組元素
for (T t : arr) {
System.out.print(t + " ");
}
System.out.println();
}

public static void main(String[] args) {
Integer[] nums= {100,39,8,200,65};
//調(diào)用泛型方法
printArray(nums);
}
}

  在上面的代碼中,printArray()就是一個泛型方法,該方法中使用了類型參數(shù)T。并且我們在方法的參數(shù)中,使用類型參數(shù)T定義了一個泛型數(shù)組T[],接著對該數(shù)組進行排序和遍歷。這樣以后無論我們傳入任何類型的數(shù)組,都可以在不進行類型轉(zhuǎn)換的前提下,輕松實現(xiàn)排序等功能了,這樣我們之前提的需求也就很容易實現(xiàn)了。

  二. 通配符

  除了以上這些用法之外,泛型中還有一個很重要的通配符功能,接下來我們就來看看它是怎么回事。

  1.簡介

  泛型中的通配符其實也是一種特殊的泛型類型,也稱為通配符類型參數(shù)。利用通配符類型參數(shù),可以讓我們編寫出更通用的代碼,甚至可以在不知道實際類型的情況下使用它們。我們一般是使用 ? 來代替具體的類型參數(shù),例如 List 在邏輯上可以等同于 List、List 等所有 List<具體類型實參> 的類。

  對此,有的小伙伴可能會很好奇,我們?yōu)槭裁葱枰ㄅ浞?其實之所以會出現(xiàn)通配符,主要是在開發(fā)時,有時候我們需要一個泛型類型,但我們卻不知道該使用哪個具體的類型。在這種情況下,我們就可以使用通配符類型參數(shù),讓代碼更加地通用。比如,我們想編寫一個可以接受任何類型的集合,并返回其中最大的元素時,此時我們可能并不確定到底該傳入哪個具體的集合,那使用通配符就會更好一些。

  2.通配符的形式

  泛型通配符在具體使用時,有如下三種實現(xiàn)形式:

  ● 未限定通配符(?):?表示未知類型的通配符;

  ● 上限通配符(? extends T):?表示類型上限的通配符,T是一個類或接口;

  ● 下限通配符(? super T):?表示類型下限的通配符,T是一個類或接口。

  接下來小編針對以上這三種形式,分別通過幾個案例來給大家講解其用法。

  3.未限定通配符(?)

  未限定通配符(?)是一種表示未知類型的通配符,它可以在需要一個類型參數(shù)的情況下使用。但由于沒有限制,因此它只能用于簡單的情況,例如集合中的迭代器或者返回類型是泛型的方法等。下面是一個簡單的例子:  

import java.util.ArrayList;
import java.util.List;

/**
* @author 一一哥Sun
*/
public class Demo05 {

public static void main(String[] args) {
List<String> names = new ArrayList<String>();
List<Integer> ages = new ArrayList<Integer>();
List<Number> numbers = new ArrayList<Number>();

names.add("一一哥");
names.add("秦始皇");
ages.add(28);
ages.add(50);
ages.add(28);
numbers.add(100);
numbers.add(800);

printElement(names);
printElement(ages);
printElement(numbers);
}

//未限定通配符的使用
public static void printElement(List<?> data) {
for(int i=0;i<data.size();i++) {
//data.getClass().getSimpleName():用于獲取某個類的類名
System.out.println(data.getClass().getSimpleName()+"--data: " + data.get(i));
}
}

}

  在這個例子中,printElement()方法就接受了一個未知類型的List集合,所以names,ages,numbers都可以作為這個方法的實參,這就是未限定通配符的作用。

  4. PECS原則

  PECS是Producer Extends Consumer Super的縮寫,這是關(guān)于Java泛型的一種設(shè)計原則。該原則表示,如果我們需要返回T,它是生產(chǎn)者(Producer),要使用extends通配符;如果需要寫入T,它就是消費者(Consumer),要使用super通配符。該原則可以指導(dǎo)我們在使用泛型時,該如何定義類型參數(shù)的上限和下限。

  當(dāng)我們使用泛型時,可能需要定義類型參數(shù)的上限和下限。例如,我們想要編寫一個方法來處理一些集合類型,但我們不知道這些集合中到底有什么類型的元素,此時我們就可以定義一個類型參數(shù)來處理所有的集合類型。一般我們可以利用extends來設(shè)置泛型上限,利用super來設(shè)置泛型下限。接下來小編會在下面的第5和第6小結(jié)中,給大家講解泛型的上限和下限具體該如何實現(xiàn),請大家繼續(xù)往下學(xué)習(xí)。

  5. 上限通配符(? extends T)

  上限通配符(?extends T)是一種表示類型上限的通配符,其中T是一個類或接口,泛型類的類型必須實現(xiàn)或繼承 T這個接口或類。它指定了可以使用的類型上限,主要是用于限制輸入的參數(shù)類型。 

import java.util.ArrayList;
import java.util.List;

/**
* @author 一一哥Sun
*/
public class Demo06 {

public static void main(String[] args) {
List<String> names = new ArrayList<String>();
List<Integer> ages = new ArrayList<Integer>();
List<Number> numbers = new ArrayList<Number>();

names.add("一一哥");
names.add("秦始皇");
ages.add(28);
ages.add(50);
ages.add(28);
numbers.add(100);
numbers.add(800);

//String等非Number類型就不行
//printElementUpbound(names);

//泛型值只能是Number及其子類類型,所以Integer/Double/Float等類型都可以,但String就不行
printElementUpbound(ages);
printElementUpbound(numbers);
}

//上限通配符的使用,這里的泛型值只能是Number及其子類類型
public static void printElementUpbound(List<? extends Number> data) {
for(int i=0;i<data.size();i++) {
//data.getClass().getSimpleName():用于獲取某個類的類名
System.out.println(data.getClass().getSimpleName()+"--data: " + data.get(i));
}
}
}

  在這個例子中,printElementUpbound方法中的集合泛型,可以是Number類或其子類,除此之外的其他類型都不行。也就是說,我們只能使用Number或其子類作為類型參數(shù),泛型類型的上限是Number,這就是上限通配符的含義。

  6. 下限通配符(? super T)

  下限通配符(?super T)是一種表示類型下限的通配符,其中T是一個類或接口。它指定了可以使用的類型下限,主要用于限制輸出的參數(shù)類型。下面是一個簡單的例子: 

import java.util.ArrayList;
import java.util.List;

/**
* @author 一一哥Sun
* V我領(lǐng)資料:syc_2312119590
* 各平臺都有小編的同名博客哦
*/
public class Demo07 {

public static void main(String[] args) {
List<String> names = new ArrayList<String>();
List<Integer> ages = new ArrayList<Integer>();
List<Double> numbers = new ArrayList<Double>();

names.add("一一哥");
names.add("秦始皇");
ages.add(28);
ages.add(50);
ages.add(28);
numbers.add(100.0);
numbers.add(800.9);

//String等非Number類型就不行
//printElementUpbound(names);

//此時Double類型也不行
//printElementDownbound(numbers);

//泛型值只能是Integer及其父類類型,所以Double/Float/String等類型都不可以
printElementDownbound(ages);

}

//下限通配符的使用,這里的泛型值只能是Integer及其父類類型
public static void printElementDownbound(List<? super Integer> data) {
for(int i=0;i<data.size();i++) {
System.out.println(data.getClass().getSimpleName()+"--data: " + data.get(i));
}
}
}

  在這個例子中,printElementDownbound方法中的集合泛型,可以是Integer或其父類型,即類型下限是Integer,除此之外的其他類型都不行。也就是說,我們只能使用Integer或其父類作為類型參數(shù),泛型類型的下限是Integer,這就是下限通配符的含義。

  7. 的區(qū)別

  在這里,小編要給大家再總結(jié)一下的區(qū)別:

  ● 允許調(diào)用T get()這樣的讀方法來獲取T對象的引用,但不允許調(diào)用set(T)這樣的寫方法來傳入T的引用(傳入null除外);

  ● 允許調(diào)用set(T)這樣的寫方法傳入T對象的引用,但不允許調(diào)用T get()這樣的讀方法來獲取T對象的引用(獲取Object除外)。

  ● 即允許讀不允許寫,允許寫不允許讀。

  大家注意,無論是未限定通配符、上限通配符還是下限通配符,我們既可以在方法中使用,也可以在類或接口中使用。

  三. 泛型擦除

  我們在學(xué)習(xí)泛型時,除了要掌握上面這些泛型類、泛型接口、泛型方法以及通配符等內(nèi)容之外,還要學(xué)習(xí)泛型擦除的相關(guān)內(nèi)容。那么什么是泛型擦除呢?我們繼續(xù)往下學(xué)習(xí)吧。

  1.簡介

  所謂的泛型擦除(Type Erasure),就是指在編譯時,JVM編譯器會將所有的泛型信息都擦除掉,變成原始類型,一般是將泛型的類型參數(shù)替換成具體類型的上限或下限(如果沒有指定上界,則默認(rèn)為Object)。

  換句話說,雖然我們在代碼中使用了泛型,但在編譯后,所有的泛型類型都會被擦除掉,轉(zhuǎn)而使用其對應(yīng)的原始類型。這就是Java泛型的底層實現(xiàn)原理。這樣設(shè)計的目的是為了兼容舊的JDK版本,使得Java具有了較好的向后兼容性,舊的非泛型代碼可以直接使用泛型類庫,而不需要進行任何修改。同時,Java也提供了反射機制來操作泛型類型,使得泛型類型在某些情況下還是可以被獲取到的,所以即使有泛型擦除,仍然也不會太影響Java虛擬機的運行時效率。

  比如,在我們定義一個泛型類時,我們會使用泛型類型參數(shù)來代替具體的類型,好比下面這個例子:

public class Box<T> {
private T content;

public Box(T content) {
this.content = content;
}

public T getContent() {
return content;
}

public void setContent(T content) {
this.content = content;
}
}

  2.泛型擦除帶來的限制

  在編譯之后,這個泛型類的類型參數(shù)T就會被擦除,成為其對應(yīng)的原始類型Object。這也意味著,我們無法在運行時獲取到泛型的實際類型參數(shù),所以泛型擦除的使用會有一些限制。首先由于泛型類型參數(shù)被擦除了,因此我們在運行時就無法獲得泛型類型參數(shù)的信息。例如,如果我們有一個List類型的變量,在運行時我們就無法獲得這個List集合中的元素類型是Integer。另一個限制是在使用泛型類型時,還需要注意類型安全性。在編譯階段,編譯器會檢查泛型類型的類型安全性;但在運行階段,由于泛型類型參數(shù)被擦除了,因此就無法保證類型安全性了。泛型擦除的限制,主要表現(xiàn)在以下幾個方面:

  無法使用基本類型實例化類型參數(shù);

  無法在運行時獲取泛型類型信息;

  泛型類型參數(shù)不能用于靜態(tài)變量或靜態(tài)方法;

  不能實例化T類型。

  接下來小編再給大家具體分析一下這些限制。

  2.1 無法使用基本類型實例化類型參數(shù)

  Java泛型中的類型參數(shù)不能是基本類型,只能是類或接口類型。例如,以下代碼在編譯階段會出錯,無法通過編譯:  

List<int> list = new ArrayList<int>();

  正確的寫法是使用基本類型對應(yīng)的包裝類型,如下所示:  

List<Integer> list = new ArrayList<Integer>();

  2.2 無法在運行時獲取泛型類型信息

  由于泛型擦除的存在,導(dǎo)致我們在程序運行時無法獲取泛型類型的信息。例如,以下代碼在運行時就無法獲取List的元素類型:  

List<String> list = new ArrayList<String>(); 
Class<?> clazz = list.getClass();
Type type = clazz.getGenericSuperclass();
// 輸出:class java.util.ArrayList<E>
System.out.println(type);

  在輸出的結(jié)果中,我們只能得到ArrayList的類型信息,而無法獲取到集合中具體的泛型類型信息,也就是獲取不到String的信息。但如果我們就是想在運行時獲取到泛型的實際類型參數(shù),其實可以參考以下方式進行實現(xiàn): 

public class Box<T> {
private T content;

public Box(T content) {
this.content = content;
}

public T getContent() {
return content;
}

public void setContent(T content) {
this.content = content;
}

public Class<?> getContentType() {
return content.getClass();
}
}

  在上面的代碼中,我們新增了一個方法 getContentType(),該方法用于返回泛型類型參數(shù)的實際字節(jié)碼類型,以后我們通過調(diào)用這個方法,就可以間接地獲取到泛型類型的信息了。

  2.3 泛型類型參數(shù)不能用于靜態(tài)變量或靜態(tài)方法

  由于泛型類型參數(shù)是在實例化對象時才被確定的,因此不能在靜態(tài)變量或靜態(tài)方法中使用泛型類型參數(shù)。例如,以下代碼是無法編譯通過的:  

public class MyClass<T> {   
//這樣的代碼編譯不通過
private static T value;

public static void setValue(T value) {
MyClass.value = value;
}
}

  正確的寫法是使用一個實際類型來代替泛型類型參數(shù):  

public class MyClass {     
private static String value;
public static void setValue(String value) {
MyClass.value = value;
}
}

  2.4 不能實例化T類型

  比如在下面的案例中:  

public class MyClass<T> {
private T first;
private T last;

public MyClass() {
first = new T();
last = new T();
}
}

  上述代碼無法通過編譯,因為構(gòu)造方法的兩行語句: 

first = new T(); 
last = new T();

  擦拭后實際上變成了:  

first = new Object(); 
last = new Object();

  這樣一來,創(chuàng)建new MyClass()和創(chuàng)建new MyClass()就變成了Object,編譯器會阻止這種類型不對的代碼。如果我們想對泛型T進行實例化,需要借助Class參數(shù)并集合反射技術(shù)來實現(xiàn),且在使用時也必須傳入Class。

  四. 結(jié)語

  不過,盡管泛型擦除有一些限制,但泛型仍然不失為一種強大的編程工具,它可以提高代碼的可讀性和可維護性。通過合理地使用泛型,我們可以在編譯時進行類型檢查,避免類型轉(zhuǎn)換的錯誤和運行時異常,從而提高了代碼的安全性和可靠性。同時,我們也需要了解Java泛型擦除的限制,以便在實際應(yīng)用中做出正確的決策。

聲明:本站稿件版權(quán)均屬千鋒教育所有,未經(jīng)許可不得擅自轉(zhuǎn)載。
10年以上業(yè)內(nèi)強師集結(jié),手把手帶你蛻變精英
請您保持通訊暢通,專屬學(xué)習(xí)老師24小時內(nèi)將與您1V1溝通
免費領(lǐng)取
今日已有369人領(lǐng)取成功
劉同學(xué) 138****2860 剛剛成功領(lǐng)取
王同學(xué) 131****2015 剛剛成功領(lǐng)取
張同學(xué) 133****4652 剛剛成功領(lǐng)取
李同學(xué) 135****8607 剛剛成功領(lǐng)取
楊同學(xué) 132****5667 剛剛成功領(lǐng)取
岳同學(xué) 134****6652 剛剛成功領(lǐng)取
梁同學(xué) 157****2950 剛剛成功領(lǐng)取
劉同學(xué) 189****1015 剛剛成功領(lǐng)取
張同學(xué) 155****4678 剛剛成功領(lǐng)取
鄒同學(xué) 139****2907 剛剛成功領(lǐng)取
董同學(xué) 138****2867 剛剛成功領(lǐng)取
周同學(xué) 136****3602 剛剛成功領(lǐng)取
相關(guān)推薦HOT
PUE是什么?

一、PUE是什么PUE,即功耗比(Power Usage Effectiveness),是數(shù)據(jù)中心的能源效率指標(biāo)。它是數(shù)據(jù)中心總功耗與設(shè)備功耗的比值,用于評估數(shù)據(jù)中...詳情>>

2023-10-15 07:13:07
graph cut和graph cuts有什么區(qū)別?

1.語境不同graph cut”通常在描述一個操作時使用,比如”perform a graph cut”,它指的是在圖中找到一個切割,將圖劃分為兩個...詳情>>

2023-10-15 07:02:16
什么是雙機熱備?

一、雙機熱備的原理雙機熱備是指在系統(tǒng)中配置兩臺服務(wù)器(主服務(wù)器和備份服務(wù)器),兩者通過高速網(wǎng)絡(luò)連接進行實時數(shù)據(jù)同步和狀態(tài)同步。主服務(wù)器...詳情>>

2023-10-15 06:37:02
偏最小二乘支持向量機和支持向量機回歸的區(qū)別是什么?

1.模型構(gòu)建的理論基礎(chǔ)不同支持向量機回歸(SVR)基于統(tǒng)計學(xué)習(xí)理論,其主要思想是找到一個超平面,使得大部分?jǐn)?shù)據(jù)點都在這個超平面的一定范圍內(nèi),...詳情>>

2023-10-15 06:30:45
VAE、GAN和transformer有什么區(qū)別?

1.模型結(jié)構(gòu)不同VAE(變分自編碼器)是一種生成模型,其基于概率圖模型和自編碼器,能夠?qū)W習(xí)數(shù)據(jù)的潛在分布。GAN(生成對抗網(wǎng)絡(luò))同樣是一種生成...詳情>>

2023-10-15 06:10:12
主站蜘蛛池模板: 吃奶摸下激烈视频无遮挡| 深夜a级毛片免费视频| 啊v在线播放| 欧美日韩图片| 国产精品伦理一二三区伦理| 国产精品久久久久影院| 免费大片av手机看片| 顶级欧美色妇xxxxx| 蜜桃97爱成人| 羞羞歪歪| 好吊妞视频这里有精品| 波多野结衣护士系列播放| 中文理论片| 日本特黄特黄刺激大片| 日本动漫h在线| 杨贵妃艳史毛片在线播放免费观看| 亚洲欧美日韩综合在线播放| 久久本网站受美利坚法律保护| 午夜性影院爽爽爽爽爽爽| 国产理论视频在线观看| 九九九精品视频免费| 亚洲情a成黄在线观看| 欧美视频亚洲视频| 卡通动漫精品一区二区三区| 欧美激情一区二区| 中文字幕在线播放第一页| 小猪视频app下载版最新忘忧草b站| 用我的手指搅乱我吧第五集| 久久亚洲伊人中字综合精品| 大伊香蕉精品一区视频在线| 西西人体44rtwww高清大但| 岛国大片在线播放| 日本全套xxxx按摩| 国产黄大片在线观看| 久久99精品久久久久久水蜜桃| 国产一区二区三区精品视频| 日韩精品一区二区三区视频| 扒开女人内裤边吃奶边摸| 日韩av片无码一区二区不卡电影| 最好看的免费观看视频| 免费看的黄色大片|