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

Java?中泛型?T?和???的區(qū)別詳解

 更新時間:2022年01月09日 10:39:45   作者:dying?擱淺  
本文主要介紹了Java?中泛型?T?和???的區(qū)別,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下

泛型中 T 類型變量 和 ? 通配符 區(qū)別

定義不同 :T 是類型變量,? 是通配符

使用范圍不同:

  • ? 通配符用作 參數(shù)類型、字段類型、局部變量類型,有時作為返回類型(但請避免這樣做)
  • T 用作 聲明類的類型參數(shù)、通用方法的類型參數(shù) (這里注意 類型參數(shù) 和 參數(shù)類型 是兩個概念)

通常我們使用 ? 的時候并并不知道也不關(guān)心這個時候的類型,這里只想使用其通用的方法,而且 ? 通配符是無法作用于聲明類的類型參數(shù),一般作用于方法和參數(shù)上。而 類型變量 T 在類定義時具有更廣泛的應用。

在某些程度的使用上 ? 通配符與 T 參數(shù)類型是可以等效的,但是 T 參數(shù)類型并不支持下界限制 即 T super SomeTing 而 通配符支持 ? super SomeThing

如果你想寫一個通用的方法且該方法的邏輯不關(guān)心類型那么就大膽的用 ? 通配符來進行適配和限制吧,如果你需要作用域類型(這可能在操作通用數(shù)組類型時更明顯)或者聲明類的類型參數(shù)時請使用 T 類型變量

類型參數(shù)定義了一種代表作用域類型的變量(例如,T),通配符只是定義了一組可用于泛型類型的允許類型。通配符的意思是“在這里使用任何類型”

在泛型的使用中我們經(jīng)常可以看到這樣的用法:

public class Box<T> {
? ? // T stands for "Type"
? ? private T t;

? ? public void set(T t) { this.t = t; }
? ? public T get() { return t; }
}
List<? extends Integer> intList = new ArrayList<>();
List<? extends Number>  numList = intList;  // OK. List<? extends Integer> is a subtype of List<? extends Number>
public interface GenericProgressiveFutureListener<F extends ProgressiveFuture<?>> extends GenericFutureListener<F> {
    void operationProgressed(F future, long progress, long total) throws Exception;
}

如果你其用法和概念仍有疑問,那不妨繼續(xù)閱讀本文

了解他們的概念:Generic Types Wildcards ,以及使用。

Generic Types 類型變量

通用類型即 T、F、K、V 這樣的寫法,它是一種是通過類型參數(shù)化的通用類或接口,也可以稱之為 類型變量

類型變量可以是任何非原始類型:任何類類型、任何接口類型、任何數(shù)組類型,甚至是另一個類型變量

按照慣例,類型參數(shù)名稱是單個大寫字母。

最常用的類型參數(shù)名稱是:

  • E - 元素(被 Java 集合框架廣泛使用)
  • K - 鍵
  • N - 數(shù)字
  • T - 類型
  • V - 值
  • S、U、V 等 - 第 2、3、4 種類型

用法

1.聲明通用的類型 – 泛型類:

當我們想對通用的對象類型進行操作時我們可能想到使用 Object ,但是使用 Object 在編譯時無法進行檢查,因為 Object 是所有類的父類,這可能導致我們意圖在傳入 Integer 并可以取出 Inerger 時,在另一部分代碼錯誤的傳入了 String

public class Box {
? ? private Object object;

? ? public void set(Object object) { this.object = object; }
? ? public Object get() { return object; }
}

為了避免上述的問題,我們可以選擇使用 類型變量

public class Box<T> {
? ? // T stands for "Type"
? ? private T t;

? ? public void set(T t) { this.t = t; }
? ? public T get() { return t; }
}

你也可以使用多個類型參數(shù)

public interface Pair<K, V> {
? ? public K getKey();
? ? public V getValue();
}

public class OrderedPair<K, V> implements Pair<K, V> {

? ? private K key;
? ? private V value;

? ? public OrderedPair(K key, V value) {
?? ?this.key = key;
?? ?this.value = value;
? ? }

? ? public K getKey()?? ?{ return key; }
? ? public V getValue() { return value; }
}

2.聲明通用的方法 – 泛型方法:

泛型方法 是引入自己的類型參數(shù)的方法。這類似于聲明泛型類型,但類型參數(shù)的范圍僅限于聲明它的方法。允許靜態(tài)和非靜態(tài)泛型方法,以及泛型類構(gòu)造函數(shù)。

泛型方法的語法包括一個類型參數(shù)列表,在尖括號內(nèi),它出現(xiàn)在方法的返回類型之前。對于靜態(tài)泛型方法,類型參數(shù)部分必須出現(xiàn)在方法的返回類型之前。

public class Util {
? ? public static <K, V> boolean compare(Pair<K, V> p1, Pair<K, V> p2) {
? ? ? ? return p1.getKey().equals(p2.getKey()) &&
? ? ? ? ? ? ? ?p1.getValue().equals(p2.getValue());
? ? }
}

public static <T> void printListT(List<T> list) {
? ? for (Object elem : list)
? ? ? ? System.out.println(elem + " ");
? ? System.out.println();
}

一個完整的調(diào)用是

JestTestMain.<String>printListT(names);

但是通??梢允÷灶愋停@里使用到的功能是 類型推斷

JestTestMain.printListT(names);

有界類型參數(shù)

同時我們可以對類型參數(shù)進行限制通過 extends 關(guān)鍵字

如 <T extends Number> 這里的泛型參數(shù)就限制了必須繼承于 Number 類。

public static <T extends Number> void printListT(List<T> list) {
    for (Object elem : list)
        System.out.println(elem + " ");
    System.out.println();
}

同時 Java 也支持多重限定,如 <T extends CharSequence & Comparable<T> & Serializable> 但是如果其中限定包含 類 需要寫在最前面

public static <T extends CharSequence & Comparable<T> & Serializable> void printListT(List<T> list) {
    for (Object elem : list)
        System.out.println(elem + " ");
    System.out.println();
}

Wildcards 通配符

通配符即指 ?

在泛型代碼中,? 表示未知類型。通配符可用于多種情況:

作為參數(shù)、字段或局部變量的類型,有時作為返回類型(但請避免這樣做)。

通配符從不用作泛型方法調(diào)用、泛型類實例創(chuàng)建或超類型的類型參數(shù)。

用法

通配符分為 3 種:

1.上界通配符:? extend 上界類型

List public static void process(List list) { /* ... */ }

我們可以使用上界通配符來放寬對變量的限制

2.無界通配符:?

如 List<?> 這表示未知類型的列表,一般有兩種情況下無界通配符是有用的:

  • 你正在編寫可以使用 Object類中提供的功能實現(xiàn)的方法
  • 當代碼使用不依賴于類型參數(shù)的泛型類中的方法時。例如,List.size或 List.clear。事實上,Class<?> 之所以如此常用,是因為 Class<T>中的大多數(shù)方法都不依賴于 T。

如何理解這句話的意思呢?來看一個例子:

public static void printList(List<Object> list) {
    for (Object elem : list)
        System.out.println(elem + " ");
    System.out.println();
}

printList 的意圖是想打印任何類型的列表,但是它沒有達到目標,其只打印了 Object 實例的列表。它不能打印 List<Integer>、List<String>、List<Double>等,因為它們不是 List<Object> 的子類型。

編譯時將會報錯。

這里我們換成通配符將正確運行

public class JestTestMain {
? ? public static void main(String[] args) {
? ? ? ? List<String> names= Lists.newArrayList();
? ? ? ? names.add("張三");
? ? ? ? names.add("張三1");
? ? ? ? names.add("張三2");
? ? ? ? printList(names);
? ? }

? ? public static void printList(List<?> list) {
? ? ? ? for (Object elem : list)
? ? ? ? ? ? System.out.println(elem + " ");
? ? ? ? System.out.println();
? ? }
}

打印:

張三 
張三1 
張三2 

這里需要明白的一點是,List<Object> 和 List<?> 并不相同,你可以向 List<Object> 中插入 Object 對象,或者任何其子類對象,但是你只能向 List<?> 中插入 null 值。

3.下界通配符:? super 子類

如:<? super Integer>

假設你要編寫一個將 Integer 對象放入列表的方法。為了最大限度地提高靈活性,希望該方法適用于 List<Integer>、List<Number>和 List<Object> 任何可以保存 Integer 值的東西。

public static void addNumbers(List<? super Integer> list) {
    for (int i = 1; i <= 10; i++) {
        list.add(i);
    }
}

類型擦除

我們要知道的一件事兒,編譯器在編譯時清除了所有類型參數(shù),也就是說會將我們的類型參數(shù)進行實際的替換。

就算如此我們?nèi)杂惺褂梅盒偷睦碛?/p>

  • Java 編譯器在編譯時對泛型代碼執(zhí)行更嚴格的類型檢查。
  • 泛型支持編程類型作為參數(shù)。
  • 泛型能夠?qū)崿F(xiàn)泛型算法。

Java 語言中引入了泛型以在編譯時提供更嚴格的類型檢查并支持泛型編程。為了實現(xiàn)泛型,Java 編譯器將類型擦除應用于:

  • 如果類型參數(shù)是無界的,則將泛型類型中的所有類型參數(shù)替換為其邊界或 Object。因此,生成的字節(jié)碼僅包含普通的類、接口和方法。
  • 必要時插入類型轉(zhuǎn)換以保持類型安全。
  • 生成橋接方法以保留擴展泛型類型中的多態(tài)性。

類型擦除確保不會為參數(shù)化類型創(chuàng)建新類;因此,泛型不會產(chǎn)生運行時開銷。

下面舉兩個例子

// 類型擦除前
public class Pair<K, V> {

? ? public Pair(K key, V value) {
? ? ? ? this.key = key;
? ? ? ? this.value = value;
? ? }

? ? public K getKey(); { return key; }
? ? public V getValue(); { return value; }

? ? public void setKey(K key) ? ? { this.key = key; }
? ? public void setValue(V value) { this.value = value; }

? ? private K key;
? ? private V value;
}
// 類型擦除后
public class Pair {

? ? public Pair(Object key, Object value) {
? ? ? ? this.key = key;
? ? ? ? this.value = value;
? ? }

? ? public Object getKey() ? { return key; }
? ? public Object getValue() { return value; }

? ? public void setKey(Object key) ? ? { this.key = key; }
? ? public void setValue(Object value) { this.value = value; }

? ? private Object key;
? ? private Object value;
}

// 類型擦除前
public static <T extends Comparable<T>> int findFirstGreaterThan(T[] at, T elem) {
? ? // ...
}
// 類型擦除后
public static int findFirstGreaterThan(Comparable[] at, Comparable elem) {
? ? // ...
}

最后感興趣的同學可以參考:

Java Tutorial on Generics
Generics in the Java programming language

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

相關(guān)文章

  • Java的JSON轉(zhuǎn)換類庫GSON的基礎使用教程

    Java的JSON轉(zhuǎn)換類庫GSON的基礎使用教程

    GSON是谷歌開源的一款Java對象與JSON對象互相轉(zhuǎn)換的類庫,Java的JSON轉(zhuǎn)換類庫GSON的基礎使用教程,需要的朋友可以參考下
    2016-06-06
  • spring data jpa 創(chuàng)建方法名進行簡單查詢方式

    spring data jpa 創(chuàng)建方法名進行簡單查詢方式

    這篇文章主要介紹了spring data jpa 創(chuàng)建方法名進行簡單查詢方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-02-02
  • Springboot初始化項目并完成登入注冊的全過程

    Springboot初始化項目并完成登入注冊的全過程

    工作之余,想要學習一下SpringBoot,通過網(wǎng)絡大量教程最終成功運行SpringBoot項目,下面這篇文章主要給大家介紹了關(guān)于Springboot初始化項目并完成登入注冊的相關(guān)資料,需要的朋友可以參考下
    2022-10-10
  • jar命令的用法詳解

    jar命令的用法詳解

    這篇文章主要介紹了jar命令的用法,非常實用,需要的朋友可以參考下
    2014-08-08
  • 淺析Java中如何優(yōu)雅地處理null值

    淺析Java中如何優(yōu)雅地處理null值

    這篇文章主要為大家詳細介紹了如何結(jié)合 Lambda 表達式和 Optional,讓 Java 更優(yōu)雅地處理 null 值,感興趣的小伙伴可以跟隨小編一起學習一下
    2025-04-04
  • Java之SpringBoot-Thymeleaf詳情

    Java之SpringBoot-Thymeleaf詳情

    聊Thymeleaf,需要知道為什么到了SpringBoot中就不用JSP了?這跟SpringBoot打包方式有點關(guān)系,SpringBoot項目打包是jar包,下面文章小編就對此做一個詳細介紹,需要的朋友可以參考一下
    2021-09-09
  • Java生成讀取條形碼和二維碼的簡單示例

    Java生成讀取條形碼和二維碼的簡單示例

    條形碼(barcode)是將寬度不等的多個黑條和空白,按照一定的規(guī)則排列,用來表示一組信息的圖形標識符,而二維碼大家應該都很熟悉了,這篇文章主要給大家介紹了關(guān)于Java生成讀取條形碼和二維碼的相關(guān)資料,需要的朋友可以參考下
    2021-07-07
  • maven打包web項目時同時打包為war和jar文件的方法

    maven打包web項目時同時打包為war和jar文件的方法

    本篇文章主要介紹了maven打包web項目時同時打包為war和jar文件的方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-10-10
  • Java使用Flyway實現(xiàn)數(shù)據(jù)庫版本控制的技術(shù)指南

    Java使用Flyway實現(xiàn)數(shù)據(jù)庫版本控制的技術(shù)指南

    在現(xiàn)代應用開發(fā)中,數(shù)據(jù)庫結(jié)構(gòu)經(jīng)常隨著業(yè)務需求不斷演變,使用手動SQL腳本管理數(shù)據(jù)庫版本,不僅容易出現(xiàn)錯誤,還難以跟蹤和回滾,Flyway是一個強大的數(shù)據(jù)庫遷移工具,能夠幫助開發(fā)者高效管理和自動化數(shù)據(jù)庫的版本控制,本文將介紹Flyway的基本功能及其在SpringBoot項目中的實踐
    2025-02-02
  • SpringMVC的概念以及快速入門示例

    SpringMVC的概念以及快速入門示例

    這篇文章主要介紹了SpringMVC的概念以及快速入門示例,SpringMVC 已經(jīng)成為目前最主流的MVC框架之一,它通過一套注解,讓一個簡單的 Java 類成為處理請求的控制器,而無須實現(xiàn)任何接口,需要的朋友可以參考下
    2023-05-05

最新評論

天峨县| 临猗县| 武邑县| 淮南市| 沛县| 白山市| 涞源县| 洱源县| 会昌县| 灌云县| 日土县| 正阳县| 新野县| 漳州市| 和静县| 射阳县| 揭阳市| 肇州县| 霍林郭勒市| 鹤山市| 朔州市| 兴义市| 南和县| 左权县| 固安县| 诏安县| 泰和县| 玉环县| 盘山县| 泾阳县| 贡嘎县| 新乡市| 湖北省| 老河口市| 宜城市| 休宁县| 方城县| 远安县| 宽城| 高邑县| 阿瓦提县|