欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java中的泛型和泛型通配符詳解

 更新時(shí)間:2023年07月14日 10:54:26   作者:大腦不能為空  
這篇文章主要介紹了Java中的泛型和泛型通配符詳解,泛型的作用就是在編譯的時(shí)候能夠檢查類(lèi)型安全,并且所有的強(qiáng)制轉(zhuǎn)換都是自動(dòng)和隱式的在沒(méi)有泛型的情況的下,通過(guò)對(duì)類(lèi)型Object的引用來(lái)實(shí)現(xiàn)參數(shù)的“任意化”,需要的朋友可以參考下

1. 前言

Java 泛型(generics)是 JDK 5 中引入的一個(gè)新特性, 泛型提供了編譯時(shí)類(lèi)型安全檢測(cè)機(jī)制,該機(jī)制允許開(kāi)發(fā)者在編譯時(shí)檢測(cè)到非法的類(lèi)型。

泛型的本質(zhì)是參數(shù)化類(lèi)型,也就是說(shuō)所操作的數(shù)據(jù)類(lèi)型被指定為一個(gè)參數(shù)。

2. 泛型的作用

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

public class GlmapperGeneric<T> {
    private T t;
    public void set(T t) {
        this.t = t;
    }
    public T get() {
        return t;
    }
    /**
     * 不指定類(lèi)型
     */
    public void noSpecifyType() {
        GlmapperGeneric glmapperGeneric = new GlmapperGeneric();
        glmapperGeneric.set("test");
        // 需要強(qiáng)制類(lèi)型轉(zhuǎn)換
        String test = (String) glmapperGeneric.get();
        System.out.println(test);
    }
    /**
     * 指定類(lèi)型
     */
    public void specifyType() {
        GlmapperGeneric<String> glmapperGeneric = new GlmapperGeneric();
        glmapperGeneric.set("test");
        // 不需要強(qiáng)制類(lèi)型轉(zhuǎn)換
        String test = glmapperGeneric.get();
        System.out.println(test);
    }
}

上面這段代碼中的 specifyType 方法中 省去了強(qiáng)制轉(zhuǎn)換,可以在編譯時(shí)候檢查類(lèi)型安全,可以用在類(lèi),方法,接口上。

3. 泛型通配符

在查看源碼時(shí),能發(fā)現(xiàn)有各種沒(méi)有見(jiàn)過(guò)的泛型通配符,例如:T、K、V、E、?等等,那這些通配符究竟有什么意義呢?

3.1 常用的K、V、T、E、?

本質(zhì)上這些通配符沒(méi)有任何區(qū)別,只是程序員在編碼過(guò)程中的一些約定俗成的規(guī)范。比如上述代碼中的 T ,我們可以換成 A-Z 之間的任何一個(gè) 字母都可以,并不會(huì)影響程序的正常運(yùn)行,但是如果換成其他的字母代替 T ,在可讀性上可能會(huì)弱一些。通常情況下,T,E,K,V,?是這樣約定的:

  •  表示不確定的 java 類(lèi)型
  • T (type) 表示具體的一個(gè)java類(lèi)型
  • K V (key value) 分別代表java鍵值中的Key Value
  • E (element) 代表Element

3.2 無(wú)界通配符 “?”

可以指定任意的類(lèi)型,沒(méi)有任何限制作用。

例如:

//測(cè)試泛型的定義
public class Generic<T> {
    private T name;
    private T flag;
    public void setFlag(T flag){
        this.flag = flag;
    }
    public T getFlag(){
        return this.flag;
    }
}
public class ShowMsg {
    /*如果在Generic對(duì)象中確定了類(lèi)型,那么調(diào)用
    例如定義的對(duì)象為Generic<String> g時(shí),只
    能輸出String類(lèi)型的getFlag(),而Generic<?>
    則表示通配任何類(lèi)型*/
    public void showFlag(Generic<?> g){
        System.out.println(g.getFlag());
    }
}
//測(cè)試無(wú)界通配符
public class Test06 {
    public static void main(String[] args) {
        ShowMsg s = new ShowMsg();
        Generic<Integer> c = new Generic<>();
        c.setFlag(100);
        s.showFlag(c);
        Generic<Number> c1 = new Generic<>();
        c1.setFlag(20);
        s.showFlag(c1);
        Generic<String> c2 = new Generic<>();
        c2.setFlag("oldlu");
        s.showFlag(c2);
    }
}

3.3 上屆通配符 <? extend E>

特征:extend 關(guān)鍵字聲明,表示參數(shù)化的類(lèi)型可能是所指定的類(lèi)型,或者是此類(lèi)型的子類(lèi)。

好處:

  • 如果傳入的類(lèi)型不是 E 或者 E 的子類(lèi),編譯不成功
  • 泛型中可以使用 E 的方法,要不然還得強(qiáng)轉(zhuǎn)成 E 才能使用

舉例:

在這里插入圖片描述

3.4 下屆通配符 <? supper E>

特征:supper 關(guān)鍵字聲明,表示參數(shù)化的類(lèi)型可能是所指定的類(lèi)型,或者是此類(lèi)型的父類(lèi)型,直至 Object。

注意:在類(lèi)型參數(shù)中使用 super 表示這個(gè)泛型中的參數(shù)必須是 E 或者 E 的父類(lèi)。

舉例:

在這里插入圖片描述

泛型限制為 貓科動(dòng)物 或者 貓科動(dòng)物的父類(lèi),所以 作為子類(lèi),是不能傳入的。

注意: 上界通配符主要用于讀數(shù)據(jù),下界通配符主要用于寫(xiě)數(shù)據(jù)。

3.5 ?和 T 的區(qū)別

?和 T 都表示不確定的類(lèi)型,區(qū)別在于我們可以對(duì) T 進(jìn)行操作,但是對(duì) ?不行,比如如下這種 :

// 可以
T t = operate();
// 不可以
?car = operate();

區(qū)別1:可以通過(guò) T 保證參數(shù)的一致性

泛型方法的定義:

interface MyGeneric {
    // 通過(guò) T 來(lái) 確保 泛型參數(shù)的一致性
    <T> void testT(List<T> dest, List<T> src);
    //通配符是 不確定的,所以這個(gè)方法不能保證兩個(gè) List 具有相同的元素類(lèi)型
    void testNon(List<?> dest, List<?> src);
}
class GlmapperGeneric<E> implements MyGeneric {
    @Override
    public <T> void testT(List<T> dest, List<T> src) {}
    @Override
    public void testNon(List<?> dest, List<?> src) {}
}
@Test
public void test() {
    GlmapperGeneric<String> glmapperGeneric = new GlmapperGeneric<>();
    List<String> dest = new ArrayList<>();
    List<Number> src = new ArrayList<>();
    // 不報(bào)錯(cuò),”?“ 忽略參數(shù)是否一致,只要傳入即可。
    glmapperGeneric.testNon(dest, src);
    // 報(bào)錯(cuò),“T” 會(huì)校驗(yàn)參數(shù)是否一致。
    glmapperGeneric.testT(dest, src);
}

區(qū)別2:類(lèi)型參數(shù)可以多重限定而通配符不行

interface MultiLimitInterfaceA {}
interface MultiLimitInterfaceB {}
class MultiLimit implements MultiLimitInterfaceA, MultiLimitInterfaceB {
    /**
     * 使用 & 符,設(shè)置多重邊界
     */
    public <T extends MultiLimitInterfaceA & MultiLimitInterfaceB> void method(T t) {
    }
}

使用 & 符號(hào)設(shè)定多重邊界(Multi Bounds),指定泛型類(lèi)型 T 必須是 MultiLimitInterfaceA 和 MultiLimitInterfaceB 的共有子類(lèi)型,此時(shí)變量 t 就具有了所有限定的方法和屬性。

對(duì)于通配符 “?” 來(lái)說(shuō),因?yàn)樗皇且粋€(gè)確定的類(lèi)型,所以不能進(jìn)行多重限定。

區(qū)別3:通配符可以使用超類(lèi)限定而類(lèi)型參數(shù)不行

例如:通配符 ? 可以

List<? extends T> getList();
List<? super T> getList();

但參數(shù) T 只能:

List<T extends A> getList();

4. Class<T> 和 Class<?> 的區(qū)別

通過(guò)動(dòng)態(tài)代理獲取實(shí)例的例子演示T和?的區(qū)別:

/**
 * Class<T> 表明是一個(gè)確定的Java類(lèi)型
 * Class<?> 是一個(gè)不確定的Java類(lèi)型
 * 如果使用Class<?>還需要強(qiáng)制類(lèi)型轉(zhuǎn)換,所以此處必須使用<T>
 */
public <T> T createInstance(Class<T> clazz) throws InstantiationException, IllegalAccessException {
    return clazz.newInstance();
}
@Test
public void test() throws InstantiationException, IllegalAccessException {
    A instance = createInstance(A.class);
    B instance1 = createInstance(B.class);
}
class A {}
class B {}

總結(jié):Class<T> 在實(shí)例化時(shí),需要將T替換成具體類(lèi)。Class<?>是通配泛型,? 可以代表任何類(lèi)型,所以主要在聲明時(shí)的限制。 例如:

// 不報(bào)錯(cuò)
public Class<?> clazz;
// 報(bào)錯(cuò)
public Class<T> clazz;

如果想Class<T>在聲明時(shí)不報(bào)錯(cuò),則當(dāng)前類(lèi)也指定泛型 T。

class Test<T> {
	public Class<?> clazz;
	// 不報(bào)錯(cuò)
	public Class<T> clazz;
}

到此這篇關(guān)于Java中的泛型和泛型通配符詳解的文章就介紹到這了,更多相關(guān)Java泛型通配符內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java Socket實(shí)現(xiàn)多線程通信功能示例

    Java Socket實(shí)現(xiàn)多線程通信功能示例

    這篇文章主要介紹了Java Socket實(shí)現(xiàn)多線程通信功能,結(jié)合具體實(shí)例形式較為詳細(xì)的分析了java多線程通信的原理及客戶端、服務(wù)器端相應(yīng)實(shí)現(xiàn)技巧,需要的朋友可以參考下
    2017-06-06
  • springboot注入servlet的方法

    springboot注入servlet的方法

    本篇文章主要介紹了springboot注入servlet的方法,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-05-05
  • springCloud項(xiàng)目搭建流程步驟分解

    springCloud項(xiàng)目搭建流程步驟分解

    SpringCloud 作為當(dāng)下最為流行的微服務(wù)框架,也越來(lái)越多的人去學(xué)習(xí)和使用這個(gè)框架。下面,我將帶大家簡(jiǎn)單地認(rèn)識(shí)一下 SpringCloud 框架,以及如何來(lái)搭建一個(gè) SpringCloud 項(xiàng)目環(huán)境的教程
    2022-05-05
  • Java中的雙重檢查(Double-Check)詳解

    Java中的雙重檢查(Double-Check)詳解

    這篇文章主要為大家詳細(xì)介紹了Java中的雙重檢查(Double-Check),感興趣的小伙伴們可以參考一下
    2016-02-02
  • Java字符串原理分析之String是否可變

    Java字符串原理分析之String是否可變

    當(dāng)我們?cè)谇舐殨r(shí),面試官很喜歡問(wèn)我們關(guān)于String的一些原理性知識(shí),比如String的不可變性、字符串的內(nèi)存分配等,為了讓大家更好地應(yīng)對(duì)面試,并理解String的底層設(shè)計(jì),接下來(lái)會(huì)給大家聊聊String的一些原理,比如String為什么具有不可變性,需要的朋友可以參考下
    2023-05-05
  • java實(shí)現(xiàn)文件夾上傳功能實(shí)例代碼(SpringBoot框架)

    java實(shí)現(xiàn)文件夾上傳功能實(shí)例代碼(SpringBoot框架)

    在web項(xiàng)目中上傳文件夾現(xiàn)在已經(jīng)成為了一個(gè)主流的需求,下面這篇文章主要給大家介紹了關(guān)于java實(shí)現(xiàn)文件夾上傳功能(springBoot框架)的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-04-04
  • Java實(shí)現(xiàn)電影院訂票系統(tǒng)代碼

    Java實(shí)現(xiàn)電影院訂票系統(tǒng)代碼

    這篇文章主要介紹了Java實(shí)現(xiàn)電影院訂票系統(tǒng)代碼,代碼實(shí)現(xiàn)了界面類(lèi)登錄注冊(cè)類(lèi),用戶類(lèi)等,具有一定參考價(jià)值,需要的朋友可以參考下。
    2017-11-11
  • java字符串轉(zhuǎn)JSON簡(jiǎn)單代碼示例

    java字符串轉(zhuǎn)JSON簡(jiǎn)單代碼示例

    這篇文章主要給大家介紹了關(guān)于java字符串轉(zhuǎn)JSON的相關(guān)資料,JSON?是一種輕量級(jí)的數(shù)據(jù)交換格式,常用于Web應(yīng)用程序中的數(shù)據(jù)傳輸,文中通過(guò)代碼示例介紹的非常詳細(xì),需要的朋友可以參考下
    2023-09-09
  • 使用java NIO及高速緩沖區(qū)寫(xiě)入文件過(guò)程解析

    使用java NIO及高速緩沖區(qū)寫(xiě)入文件過(guò)程解析

    這篇文章主要介紹了使用java NIO及高速緩沖區(qū)寫(xiě)入文件過(guò)程解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-09-09
  • JavaEE線程安全定時(shí)器模式任務(wù)

    JavaEE線程安全定時(shí)器模式任務(wù)

    這篇文章主要介紹了JavaEE線程安全定時(shí)器模式任務(wù),定時(shí)器模式像是一個(gè)鬧鐘定時(shí),在一定時(shí)間之后被喚醒并執(zhí)行某個(gè)之前設(shè)定好的任務(wù),感興趣的小伙伴可以參考一下
    2022-06-06

最新評(píng)論