最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

一文帶你搞懂Java中的泛型和通配符

 更新時(shí)間:2022年09月06日 14:11:12   作者:JAVA旭陽  
泛型機(jī)制在項(xiàng)目中一直都在使用,甚至很多源碼中都用到了泛型機(jī)制。但是里面很多的機(jī)制和特性一直沒有明白,尤其通配符這塊,經(jīng)常忘記。本文對此做了一些總結(jié),具有一定借鑒價(jià)值,希望有所幫助

概述

泛型機(jī)制在項(xiàng)目中一直都在使用,比如在集合中ArrayList<String, String>, Map<String,String>等,不僅如此,很多源碼中都用到了泛型機(jī)制,所以深入學(xué)習(xí)了解泛型相關(guān)機(jī)制對于源碼閱讀以及自己代碼編寫有很大的幫助。但是里面很多的機(jī)制和特性一直沒有明白,特別是通配符這塊,對于通配符上界、下界每次用每次百度,經(jīng)常忘記,這次我就做一個(gè)總結(jié),加深自己的理解。

泛型介紹和使用

泛型在類定義時(shí)不會設(shè)置類中的屬性或方法參數(shù)的具體類型,而是在類使用時(shí)(創(chuàng)建對象)再進(jìn)行類型的定義。會在編譯期檢查類型是否錯(cuò)誤, 保證程序的可讀性和安全性。

泛型定義根據(jù)實(shí)際情況可以分為泛型類和泛型方法:

泛型類

public class Point<T, U> {

    private T pointX;

    private U pintY;

    public Point(T pointX, U pintY) {
        this.pointX = pointX;
        this.pintY = pintY;
    }

    public void showPoint() {
        System.out.println(pointX);
        System.out.println(pintY);
    }
}
  • 類中引入類型變量,類型變量指的T, U這些,用尖括號<>括起來, 跟在類名后面。
  • 多個(gè)類型變量可以用逗號分隔。
  • 在類中的方法和返回值等地方可以使用類型變量。
  • 類型變量采用大寫形式,要求簡短,一般E表示集合的元素類型,K和V表示key和value等。
  • 泛型類使用:Point<Integer, Double>

泛型方法

public class FxMethod {

    public static <T> T getMiddleNumber(T ... numbers) {
        return null;
    }

    public <T, U> void showNumber(T t, U u) {
        System.out.println("t = " + t);
        System.out.println("u = " + u);;
    }
}
  • 方法中引入類型變量,在返回類型前添加<>, 中間放置類型變量,多個(gè)類型變量用逗號分隔。
  • 在方法的參數(shù)和返回值等位置可以使用類型變量。
  • 泛型方法使用:Integer result = FxMethod.getMiddleNumber(2, 3) 或者 Integer result = FxMethod.<Integer>getMiddleNumber(2, 3)

類型變量的限定

前面講解了泛型一般定義的兩種方式,其中的類型變量沒有任何限定, 這樣在導(dǎo)致一方面在定義泛型的時(shí)候無法使用一些API, 需要強(qiáng)轉(zhuǎn),另一方面在使用的時(shí)候也容易出錯(cuò),那么如何給類型變量添加限定呢?

  • 只有通過extends關(guān)鍵字限定,不能通過super關(guān)鍵字。
  • 加了限定以后,就可以直接使用限定類相關(guān)的API。
  • 多個(gè)限定之間用&符號,比如T extends Number & Comparable。
  • 使用泛型時(shí),只能傳入相應(yīng)限定的類,比如傳入Point<String, String> 就會報(bào)編譯錯(cuò)誤。

通配符使用

泛型的引入的確解決了很大問題,那它是完美的嗎?

class AnimalWrapper<T extends Animal> {
    private T animal;

    AnimalWrapper(T animal) {
        this.animal = animal;
    }

    public void eat() {
       animal.eat();
    }

}

class Animal {
    private String name;

    public void eat() {
        System.out.println("animal eat -----");
    }
}

class Cat extends Animal {

    @Override
    public void eat() {
        System.out.println(" cat eat -----");
    }
}

定義一個(gè)AnimalWrapper,泛型變量中限定為Animal,如果是下面的測試類,會怎么樣呢?

會編譯報(bào)錯(cuò),因?yàn)锳nimalWrapper并不是AnimalWrapper的子類,不能直接傳入。為了解決個(gè)問題,我們引入了通配符,通配符一般是在方法中或者泛型類使用中用到。

AnimalWrapper可以作為AnimalWrapper<?extends Animal>的子類型,這就是利用通配符帶來的好處。

  • 統(tǒng)配符使用在集合或者方法的參數(shù)返回值中。
  • 通配符可以分為無邊界通配符、上邊界通配符和下邊界通配符。

無邊界通配符

通配符無邊界,可以傳入任何類型,沒有限制,相當(dāng)于Object.

基本語法:

<?>

例子:

public static void printList1(List<?> list) {
        for (Object x:list) {
            System.out.println(x);
        }
    }

    public static void main(String[] args) {
        List<Integer> list = new ArrayList<>();
        list.add(1);
        printList1(list);  // ok
        List<String> list2 = new ArrayList<>();
        list2.add("1");
        printList1(list2); // ok

        
        List<?> list3 = list;
        // get只能用Object接受, 
        Object o = list3.get(0);
        list3.add(5);   // compile error
        list3.add(new Object()); // compile error
    }

小結(jié):

  • 無邊界通配符相當(dāng)于Object,任何類型都可以傳入,比如 List<Integer> list, List<String> list2 。
  • 由于?無法確定是哪種類型,所以只能使用Object類型的變量接收, 比如例子中的: Object o = list3.get(0);
  • 如果是無邊界通配符對應(yīng)的集合類型,不能添加任何元素。因?yàn)闊o法確定集合存放數(shù)據(jù)的類型,鬼知道我們要放什么類型才合適啊。

通配符上界

通配符上界,可以限制傳入的類型必須是上界這個(gè)類或者是這個(gè)類的子類。

基本語法:

<? extends 上界> 
<? extends Number>//可以傳入的實(shí)參類型是Number或者Number的子類

例子:

public static void printList1(List<? extends Number> list) {
        for (Object x:list) {
            System.out.println(x);
        }
    }


    public static void main(String[] args) {
        List<Integer> list = new ArrayList<>();
        list.add(1);
        printList1(list);  // ok
        List<Double> list1 = new ArrayList<>();
        list1.add(1.0D);
        printList1(list1);  // ok
        List<String> list2 = new ArrayList<>();
        list2.add("1");
        printList1(list2); // compile error


        List<? extends Number> list3 = list;
        // get能用上界
        Number o = list3.get(0);
        // 不能add
        list3.add(5);   // compile error
        list3.add(new Object()); // compile error

    }

小結(jié):

  • 通配符上界? extends A, 表明所有的是A的類或者子類型可以傳入,比如本例中的Integer和Double都是Number的子類,String不是。
  • 通配符上界? extends A,確定了類型是A或者是A的子類,那么向集合容器get獲取數(shù)據(jù),肯定是它的上界類A,因?yàn)槠渌诺念惗际茿的子類,比如例子中的 Number o = list3.get(0);
  • 如果向通配符上界集合中添加元素時(shí),會失敗。 List<? extends A>, 說明容器可以容納的是A或者A的子類,但A的子類有很多,不確定放哪個(gè),為了安全性,就直接不讓你add,比如例子中的list3.add(5); ,5雖然是Number的子類,依然不能add。

通配符下界

通配符下界,可以限制傳入的類型必須是這個(gè)類或者是這個(gè)類的父類。

基本語法:

<? super 下界> 
<? super Integer>//代表 可以傳入的實(shí)參的類型是Integer或者Integer的父類類型

例子:

public static void printList1(List<? super Integer> list) {
        for (Object x:list) {
            System.out.println(x);
        }
    }


    public static void main(String[] args) {
        List<Integer> list = new ArrayList<>();
        list.add(1);
        printList1(list);  // ok
        List<Double> list1 = new ArrayList<>();
        list1.add(1.0D);
        printList1(list1);  // compile error
        List<String> list2 = new ArrayList<>();
        list2.add("1");
        printList1(list2); // compile error


        List<? super Integer> list3 = list;
        // 不能用下界接收
        Integer o = list3.get(0); // compile error
        // 能add
        list3.add(5);   // ok
        list3.add(new Number(5)); // compile error

    }
  • 通配符上界? super A, 表明所有的是A的類或者A的父類可以傳入。
  • 通配符上界? super A,確定了類型是A或者是A的父類,那么向集合容器get獲取數(shù)據(jù),無法確定是A還是A的某個(gè)父類,所以不能get, Integer o = list3.get(0); // compile error,比如例子中用Integer接收,萬一list3中放的是Object類型,就涼涼了。
  • 如果向通配符下界集合中添加元素時(shí),只能添加下屆類的子類。比如例子中的:list3.add(5), list3的通配符是<? super Integer>,說明該集合存放的是Integer或者Integer的父類,我只要向容器中放Integer和它的子類都是成立的。

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

相關(guān)文章

  • 實(shí)踐講解SpringBoot自定義初始化Bean+HashMap優(yōu)化策略模式

    實(shí)踐講解SpringBoot自定義初始化Bean+HashMap優(yōu)化策略模式

    本篇講解了SpringBoot自定義初始化Bean+HashMap優(yōu)化策略模式,通過實(shí)踐的方式更通俗易懂,對此不了解的同學(xué)跟著小編往下看吧
    2021-09-09
  • Java開發(fā)過程中關(guān)于異常處理的詳解

    Java開發(fā)過程中關(guān)于異常處理的詳解

    異常是程序中的一些錯(cuò)誤,但不是所有錯(cuò)誤都是異常,且錯(cuò)誤有時(shí)候是可以避免的。比如說,你的代碼少一個(gè)分號,那運(yùn)行出來結(jié)果是提示是錯(cuò)誤 java.lang.Error;如果你用System.out.println(11/0),那么你是因?yàn)槟阌?做了除數(shù),會拋出 java.lang.ArithmeticException 的異常
    2021-10-10
  • Java 注解@PostConstruct的原理及使用場景

    Java 注解@PostConstruct的原理及使用場景

    @PostConstruct 是 Java 中用于標(biāo)記初始化方法的注解,本文將詳細(xì)講解 @PostConstruct 的原理、使用場景及最佳實(shí)踐,感興趣的朋友一起看看吧
    2025-04-04
  • Java代碼規(guī)范與質(zhì)量檢測插件SonarLint的使用

    Java代碼規(guī)范與質(zhì)量檢測插件SonarLint的使用

    本文主要介紹了Java代碼規(guī)范與質(zhì)量檢測插件SonarLint的使用,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-08-08
  • 詳解定時(shí)任務(wù)框架Quartz的使用

    詳解定時(shí)任務(wù)框架Quartz的使用

    Quartz是OpenSymphony開源組織在Job?scheduling領(lǐng)域又一個(gè)開源項(xiàng)目,完全由Java開發(fā),可以用來執(zhí)行定時(shí)任務(wù),本文就來帶大家聊聊它的具體使用
    2023-02-02
  • 詳解mybatis多對一關(guān)聯(lián)查詢的方式

    詳解mybatis多對一關(guān)聯(lián)查詢的方式

    這篇文章主要給大家介紹了關(guān)于mybatis多對一關(guān)聯(lián)查詢的相關(guān)資料,文中將關(guān)聯(lián)方式以及配置方式介紹的很詳細(xì),需要的朋友可以參考下
    2021-06-06
  • 深入SQLite多線程的使用總結(jié)詳解

    深入SQLite多線程的使用總結(jié)詳解

    本篇文章是對SQLite多線程的使用進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下
    2013-05-05
  • Java網(wǎng)絡(luò)編程基礎(chǔ)篇之單向通信

    Java網(wǎng)絡(luò)編程基礎(chǔ)篇之單向通信

    這篇文章主要介紹了Java網(wǎng)絡(luò)編程里通過套接字實(shí)現(xiàn)單向通信的方法及相關(guān)實(shí)例,屬于網(wǎng)絡(luò)編程入門程序,雖然簡單,但具有一定參考價(jià)值,需要的朋友可以參考下。
    2017-09-09
  • Java讀取文本文件的各種方法

    Java讀取文本文件的各種方法

    這篇文章主要介紹了Java讀取文本文件的各種方法,在 Java 中有多種方法可以讀取純文本文件,例如你可以使用FileReader、BufferedReader或Scanner來讀取文本文件,感興趣的小伙伴和小編一起進(jìn)入文章了解更多內(nèi)容吧,希望能幫助到大家
    2021-11-11
  • SpringBoot集成Validation參數(shù)校驗(yàn)

    SpringBoot集成Validation參數(shù)校驗(yàn)

    這篇文章主要為大家詳細(xì)介紹了SpringBoot集成Validation參數(shù)校驗(yàn),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-01-01

最新評論

锡林浩特市| 临泉县| 长沙市| 华坪县| 屏山县| 林周县| 安图县| 大竹县| 长寿区| 福州市| 娄底市| 阿巴嘎旗| 乐至县| 开原市| 大竹县| 拉萨市| 明溪县| 达孜县| 杭锦后旗| 石首市| 青田县| 合水县| 临西县| 新宾| 垦利县| 江源县| 垣曲县| 沾益县| 大方县| 通化县| 萨迦县| 海林市| 巴青县| 遂平县| 天气| 鹰潭市| 芷江| 航空| 湛江市| 新晃| 二连浩特市|