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

Java中的泛型使用詳解

 更新時間:2025年10月19日 10:42:35   作者:新綠MEHO  
本文給大家介紹java中的泛型知識,包括基本語法使用方法,本文結(jié)合實例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友參考下吧

泛型類

語法

class 泛型類名稱<類型形參列表> {
        // 這里可以使用類型參數(shù)
}
class ClassName<T1, T2, ..., Tn> {
}
class 泛型類名稱<類型形參列表> extends 繼承類/* 這里可以使用類型參數(shù) */ {
        // 這里可以使用類型參數(shù)
}
class ClassName<T1, T2, ..., Tn> extends ParentClass<T1> {
        // 可以只使用部分類型參數(shù)
}

使用

泛型類<類型實參> 變量名; // 定義一個泛型類引用
new 泛型類<類型實參>(構(gòu)造方法實參); // 實例化一個泛型類對象 

class MyArray<T> {
    public Object[] array = new Object[10];
    public void set(int pos,T val) {
        array[pos] = val;
    }
    public T get(int pos) {
        return (T)array[pos];
    }
    public Object[] getArray() {
        return array;
    }
}
public class Test {
    public static void main(String[] args) {
        MyArray<String> myArray = new MyArray<>();
    }
}

泛型上界

在定義泛型類時,有時需要對傳入的類型變量做一定的約束,可以通過類型邊界來約束。

定義

class 泛型類名稱<類型形參 extends 類型邊界> {
        ...
} 

使用

class MyArray<T extends Number> {
    public Object[] array = new Object[10];
    public void set(int pos,T val) {
        array[pos] = val;
    }
    public T get(int pos) {
        return (T)array[pos];
    }
    public Object[] getArray() {
        return array;
    }
}
public class Test {
    public static void main(String[] args) {
          // 編譯錯誤,因為 String 不是 Number 的子類型
//        MyArray<String> myArray1 = new MyArray<>();
        // 正常,因為 Integer 是 Number 的子類型
        MyArray<Integer> myArray = new MyArray<>();
    }
}
class Alg<T extends Comparable<T>> {
    public T findMax(T[] array) {
        T max = array[0];
        for (int i = 1; i < array.length; i++) {
            if(array[i].compareTo(max) > 0) {
                max = array[i];
            }
        }
        return max;
    }
}

類型擦除

Java中的泛型擦除是Java泛型實現(xiàn)的一個關(guān)鍵特性,它允許Java在編譯時檢查類型安全,但在運行時忽略泛型信息。這意味著,盡管你可以在編譯時指定泛型類型,但在運行時,JVM看到的只是原始類型,并不保留任何關(guān)于泛型參數(shù)的信息。

class MyArray<E> {
    // E 會被擦除為 Object
}
class MyArray<E extends Comparable<E>> {
    // E 被擦除為 Comprable
}

 示例

class Alg<T extends Comparable<T>> {
    public T findMax(T[] array) {
        T max = array[0];
        for (int i = 1; i < array.length; i++) {
            if(array[i].compareTo(max) > 0) {
                max = array[i];
            }
        }
        return max;
    }
}

針對上面的代碼,編譯結(jié)果如下:

編譯器在類型擦除階段做什么?

一、擦除泛型類型信息
移除類型參數(shù):編譯器會移除所有與泛型相關(guān)的類型參數(shù)信息。這意味著在編譯后的字節(jié)碼中,將不再包含任何泛型類型參數(shù)的信息。
替換為原始類型:泛型類型參數(shù)會被替換為其上界(如果指定了上界的話,比如T extends Comparable<T>中的T會被替換為Comparable<T>;如果沒有指定上界,則默認(rèn)為Object)。例如,List<String>和List<Integer>在編譯后的字節(jié)碼中都表現(xiàn)為List。
二、調(diào)整類型信息
方法參數(shù)、局部變量和字段的類型調(diào)整:除了泛型類型本身被擦除外,編譯器還會相應(yīng)地調(diào)整方法參數(shù)、局部變量和字段的類型,以確保它們在運行時的一致性。
三、插入類型轉(zhuǎn)換
類型強(qiáng)制轉(zhuǎn)換:由于類型信息在運行時不可用,編譯器會在需要的地方插入必要的類型轉(zhuǎn)換。例如,從List<String>中獲取元素時,雖然運行時這個列表只是普通的List,但編譯器會在幕后添加一個從Object到String的顯式類型轉(zhuǎn)換。
四、確保類型安全
編譯時類型檢查:在編譯階段,編譯器會利用泛型類型信息進(jìn)行類型檢查,確保類型安全。例如,編譯器會阻止向List<String>中添加整數(shù)或其他非字符串對象,或者嘗試將List<Integer>賦值給List<Double>等不兼容的操作。
五、橋接方法的生成
向后兼容性:為了保持與未使用泛型的舊代碼的兼容性,編譯器可能會為泛型類生成橋接方法。這些橋接方法允許泛型類的方法與原生類型的方法共存,并且可以相互調(diào)用。
總的來說,編譯器在類型擦除階段的主要目標(biāo)是確保泛型代碼在運行時能夠安全、正確地執(zhí)行,同時盡量減少對現(xiàn)有代碼的影響。通過移除泛型類型信息并插入必要的類型轉(zhuǎn)換,編譯器使得泛型代碼能夠與非泛型代碼無縫對接,從而保證了Java平臺的整體一致性和穩(wěn)定性。 

通配符

?用于在泛型的使用,即為通配符。

class Message<T> {
    private T message;
    public T getMessage() {
        return message;
    }
    public void setMessage(T message) {
        this.message = message;
    }
}
public class Test{
    //可以傳入任意類型的Message
    public static void fun(Message<?> temp){
        System.out.println(temp.getMessage());
    }
    public static void main(String[] args) {
        Message<String> message = new Message<>();
        message.setMessage("你好!");
        fun(message);
        Message<Integer> message2 = new Message<>();
        message2.setMessage(199);
        fun(message2);
    }
}

通配符上界

<? extends 上界> 

上界通配符用于指定一個類型的上界,即泛型參數(shù)必須是該類型或其子類。這種通配符主要用于讀取操作,因為它允許你安全地讀取數(shù)據(jù),但不允許你寫入數(shù)據(jù)(除了null,因為null可以被視為任何類型的實例)。

特點:

add()方法:不能添加任何元素(除了null),因為編譯器無法確定具體的類型,添加其他元素可能會導(dǎo)致類型安全問題。
get()方法:可以安全地讀取元素,并且返回的類型是T或T的子類,但通常需要用T或T的父類(如Object)來接收,因為編譯器無法確定具體的子類類型。

class Food {
}
class Fruit extends Food {
}
class Apple extends Fruit {
}
class Banana extends Fruit {
}
class Message<T> {
    private T message;
    public T getMessage() {
        return message;
    }
    public void setMessage(T message) {
        this.message = message;
    }
}
public class Test1 {
    public static void funExtends(Message<? extends Fruit> temp){
        System.out.println(temp.getMessage());
        //通配符的上界來說 是不可以進(jìn)行修改元素的
/*        temp.setMessage(new Banana());
        temp.setMessage(new Apple());*/
        //向上轉(zhuǎn)型
        Fruit fruit = temp.getMessage();
    }
    public static void main(String[] args) {
        Message<Apple> message1 = new Message<>();
        message1.setMessage(new Apple());
        Message<Banana> message2 = new Message<>();
        message2.setMessage(new Banana());
        funExtends(message1);
        funExtends(message2);
    }
}

 通配符下界

<? super 下界> 

下界通配符用于指定一個類型的下界,即泛型參數(shù)必須是該類型或其父類。這種通配符主要用于寫入操作,因為它允許你安全地添加T或T的子類類型的元素,但在讀取時只能確保是Object類型。 

特點:

add()方法:可以添加T或T的子類類型的元素,因為所有這些類型都是下界類型的子類或相同類型。
get()方法:讀取元素時,由于類型的不確定性,通常只能用Object類型來接收。如果需要具體的類型,則需要進(jìn)行類型轉(zhuǎn)換。 

class Food {
}
class Fruit extends Food {
}
class Apple extends Fruit {
}
class Banana extends Fruit {
}
class Plate<T> {
    private T plate ;
    public T getPlate() {
        return plate;
    }
    public void setPlate(T plate) {
        this.plate = plate;
    }
}
public class Test1 {
    public static void funSuper(Plate<? super Fruit> temp){
        // 此時可以修改??!添加的是Fruit 或者Fruit的子類
        temp.setPlate(new Apple());//這個是Fruit的子類   向上轉(zhuǎn)型
        temp.setPlate(new Banana());//這個是Fruit的本身
//        Fruit fruit = temp.getPlate(); //不能接收,這里無法確定是哪個父類
        System.out.println(temp.getPlate());//只能直接輸出
    }
    public static void main(String[] args) {
        Plate<Fruit> message1 = new Plate<>();
        Plate<Food> message2 = new Plate<>();
        funSuper(message1);
        funSuper(message2);
    }
}

泛型方法

語法

方法限定符 <類型形參列表> 返回值類型 方法名稱(形參列表) { ... }

使用 

class Alg2 {
    //泛型方法
    public static <T extends Comparable<T>> T findMax(T[] array) {
        T max = array[0];
        for (int i = 1; i < array.length; i++) {
            if(array[i].compareTo(max) > 0) {
                max = array[i];
            }
        }
        return max;
    }
}
public class Test2 {
    public static void main1(String[] args) {
        Integer[] array = {1,13,51,71,19};
        Integer ret = Alg2.<Integer>findMax(array);
        System.out.println(ret);
    }
}

泛型的限制

1. 不能使用基本數(shù)據(jù)類型作為泛型類型參數(shù)
Java中的泛型只能使用引用數(shù)據(jù)類型作為類型參數(shù),不能使用基本數(shù)據(jù)類型(如int、double等)。如果需要使用基本數(shù)據(jù)類型的泛型,通常需要使用它們對應(yīng)的包裝類(如Integer、Double等)。

2. 不能創(chuàng)建泛型類型的數(shù)組
由于類型擦除的原因,Java不允許直接創(chuàng)建泛型類型的數(shù)組。例如,List<String>[] listArray = new ArrayList<String>[10]; 是不允許的。如果需要類似的功能,可以考慮使用ArrayList<List<String>>等集合類來實現(xiàn)。

3. 不能實例化泛型類型的對象(除了使用new操作符的匿名內(nèi)部類)
Java不允許直接實例化泛型類型的對象,如List<String> list = new List<String>(); 是不允許的。應(yīng)該使用具體的類來實例化泛型,如List<String> list = new ArrayList<>();。

4. 運行時類型查詢的限制
由于類型擦除,在運行時無法直接查詢泛型參數(shù)的具體類型。例如,instanceof 運算符和getClass()方法不能用于檢查泛型類型參數(shù)的具體類型。這意味著,在運行時,所有的泛型類型都會被當(dāng)作它們的原始類型(即擦除后的類型)來處理。

5. 泛型類型參數(shù)不具有繼承關(guān)系
即使兩個類之間存在繼承關(guān)系,它們的泛型類型參數(shù)之間也不具有繼承關(guān)系。例如,List<A>并不是List<B>的子類,即使A是B的子類。這要求開發(fā)者在編寫泛型代碼時特別注意類型安全。

6. 泛型上界和下界的限制
上界:通過extends關(guān)鍵字,可以限制泛型類型參數(shù)必須是某個類型的子類或?qū)崿F(xiàn)類。這有助于在編譯時檢查類型兼容性,提高代碼的安全性。
下界:通過super關(guān)鍵字,可以限制泛型類型參數(shù)必須是某個類型的父類型。這允許在泛型方法或類中靈活處理不同但兼容的類型。
7. 泛型通配符的限制
泛型通配符(如?、<? extends T>、<? super T>)用于表示未知類型或受限類型。然而,它們也帶來了一些限制,如在使用上界通配符時不能添加除null以外的元素,而在使用下界通配符時讀取的元素類型只能為Object等。

8. 反射和泛型
Java的反射機(jī)制可以在運行時訪問類的信息,但由于類型擦除,反射無法直接獲取泛型類型參數(shù)的具體信息。這要求開發(fā)者在使用反射和泛型時需要特別注意類型安全和類型轉(zhuǎn)換的問題。

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

相關(guān)文章

  • SpringBoot之bootstrap和application的區(qū)別解讀

    SpringBoot之bootstrap和application的區(qū)別解讀

    這篇文章主要介紹了SpringBoot之bootstrap和application的區(qū)別及說明,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-03-03
  • java中PreparedStatement和Statement詳細(xì)講解

    java中PreparedStatement和Statement詳細(xì)講解

    這篇文章主要介紹了java中PreparedStatement和Statement詳細(xì)講解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-11-11
  • mybatis-plus通用枚舉@JsonValue接收參數(shù)報錯No enum constant

    mybatis-plus通用枚舉@JsonValue接收參數(shù)報錯No enum constant

    最近在使用mybatis-plus時用到了通用枚舉,遇到了問題,本文主要介紹了mybatis-plus通用枚舉@JsonValue接收參數(shù)報錯No enum constant,具有一定的參考價值,感興趣的可以了解一下
    2023-09-09
  • Java利用java.time處理時間的方法全解析

    Java利用java.time處理時間的方法全解析

    但凡做過Java開發(fā)的程序員,幾乎都踩過時間處理的坑,這篇文章主要為大家詳細(xì)介紹了Java利用java.time處理時間的相關(guān)用法,希望對大家有所幫助
    2026-03-03
  • java.time包時間類的具體使用

    java.time包時間類的具體使用

    本文主要介紹了java.time包時間類的具體使用,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2024-08-08
  • java利用pdfbox+poi往pdf插入數(shù)據(jù)

    java利用pdfbox+poi往pdf插入數(shù)據(jù)

    這篇文章主要給大家介紹了關(guān)于java利用pdfbox+poi如何往pdf插入數(shù)據(jù)的相關(guān)資料,文中通過實例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2022-02-02
  • Java?IO及BufferedReader.readline()出現(xiàn)的Bug

    Java?IO及BufferedReader.readline()出現(xiàn)的Bug

    這篇文章主要介紹了Java?IO及BufferedReader.readline()出現(xiàn)的Bug,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-12-12
  • Java中實現(xiàn)Map按值排序的多種方法

    Java中實現(xiàn)Map按值排序的多種方法

    Java的Map接口默認(rèn)不保證元素的順序,本文介紹如何使用TreeMap、Collections.sort()結(jié)合Entry、Stream API以及Guava庫等技術(shù)手段實現(xiàn)Map按值排序,每種方法都有其特點,在選擇具體方法時應(yīng)考慮項目的具體需求及個人偏好,需要的朋友可以參考下
    2025-03-03
  • Java解除文件占用即Dom4j操作后實現(xiàn)xml關(guān)流

    Java解除文件占用即Dom4j操作后實現(xiàn)xml關(guān)流

    這篇文章主要介紹了Java解除文件占用即Dom4j操作后實現(xiàn)xml關(guān)流,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-04-04
  • JavaWeb動態(tài)導(dǎo)出Excel可彈出下載

    JavaWeb動態(tài)導(dǎo)出Excel可彈出下載

    這篇文章主要介紹了JavaWeb動態(tài)導(dǎo)出Excel,對Excel可彈出進(jìn)行下載操作,感興趣的小伙伴們可以參考一下
    2016-03-03

最新評論

沅江市| 当涂县| 东乌珠穆沁旗| 泌阳县| 石首市| 观塘区| 龙州县| 自贡市| 巴楚县| 沙湾县| 灌云县| 万年县| 阳春市| 遂宁市| 武威市| 潢川县| 株洲县| 若尔盖县| 隆德县| 平江县| 中牟县| 汨罗市| 奉贤区| 扎兰屯市| 三都| 东乡族自治县| 陈巴尔虎旗| 枣庄市| 诏安县| 三门县| 长海县| 贺州市| 高州市| 正镶白旗| 雷波县| 淮滨县| 佛坪县| 曲松县| 醴陵市| 内江市| 孟村|