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

Java集合框架入門之泛型和包裝類

 更新時(shí)間:2021年10月20日 11:47:43   作者:謝謝你,泰羅!  
Java 泛型(generics)是 JDK 5 中引入的一個(gè)新特性, 泛型提供了編譯時(shí)類型安全檢測機(jī)制,該機(jī)制允許程序員在編譯時(shí)檢測到非法的類型。泛型的本質(zhì)是參數(shù)化類型,也就是說所操作的數(shù)據(jù)類型被指定為一個(gè)參數(shù)

前言: 本章主要是為了后面學(xué)習(xí)集合框架所做的知識(shí)補(bǔ)充。補(bǔ)充了泛型以及包裝類兩個(gè)知識(shí),但是該章泛型的講解不夠全面,主要是為了集合框架學(xué)習(xí)做鋪墊。

1. 預(yù)備知識(shí)-泛型(Generic)

1.1 泛型的引入

我們之前實(shí)現(xiàn)過的順序表,實(shí)現(xiàn)的是保存某一類型的元素(如 int 型)

示例代碼:

public class MyArrayList{
    private int[] array;	  // 保存順序表的元素,元素都為 int 類型
    private int size;		  // 保存順序表內(nèi)存數(shù)據(jù)個(gè)數(shù)
	public MyArrayList(){
        this.array=new int[10];
    }
    public void add(int val){
        // 尾插
        this.array[size]=val;
        this.size++;
    }
    public int get(int index){
        // 獲取 index 位置的元素
        return this.array[index];
    }
    ...
}

但是這樣寫的話,這個(gè)順序表就只能存儲(chǔ) int 類型的元素了

如果現(xiàn)在需要保存指向 Person 類型對(duì)象的引用的順序表,該如何解決呢?如果又需要保存指向 Book 類型對(duì)象的引用呢?

  • 首先,我們在學(xué)習(xí)多態(tài)的時(shí)了解到:基類的引用可以指向子類的對(duì)象
  • 其次,我們也知道 Object 類是 Java 中所有所有類的祖先類

因此,要解決上述問題,我們可以這樣做

將我們的順序表的元素類型定義成 Object 類型,這樣我們的 Object 類型的引用可以指向 Person 類型的對(duì)象或者指向 Book 類型的對(duì)象

示例代碼:

public class MyArrayList{
    private Object[] array;	  // 保存順序表的元素,即 Object 類型的引用
    private int size;		  // 保存順序表內(nèi)存數(shù)據(jù)個(gè)數(shù)
	public MyArrayList(){
        this.array=new Object[10];
    }
    public void add(Object val){
        // 尾插
        this.array[size]=val;
        this.size++;
    }
    public Object get(int index){
        // 獲取 index 位置的元素
        return this.array[index];
    }
    ...
}

這樣,我們就可以很自由的存儲(chǔ)指向任意類型的對(duì)象的引用到我們的順序表了

示例代碼:

MyArrayList books = new MyArrayList();
for(int i=0; i<10;i++){
    books.add(new Book());	// 插入10本書到順序表
}

MyArrayList people = new MyArrayList();
for(int i=0; i<10; i++){
    people.add(new Person());	// 插入10個(gè)人到順序表
}

遺留問題: 現(xiàn)在的 MyArrayList 雖然可以做到添加任意類型的引用到其中,但會(huì)遇到下面的問題

當(dāng)我們使用這樣的代碼時(shí),明知道存儲(chǔ)的是哪種類型的元素,但還是要進(jìn)行強(qiáng)制轉(zhuǎn)換。如

MyArrayList books = new MyArrayList();
books.add(1);

// 將 Object 類型轉(zhuǎn)換為 int 類型 (需要類型轉(zhuǎn)換才能成功)
int val=(int)books.get(0);
System.out.println(val);
// 結(jié)果為:1

雖然知道返回的元素是 int 類型,但還是要進(jìn)行強(qiáng)制類型轉(zhuǎn)換

創(chuàng)建的一個(gè) MyArrayList 中可以存放各種類型,形成了一個(gè)大雜燴。并且將 Object 類型(具體是 A 類型)轉(zhuǎn)換為 B 類型時(shí),即使強(qiáng)制轉(zhuǎn)換,也會(huì)產(chǎn)生異常 ClassCastException

MyArrayList books = new MyArrayList();
books.add(new Book());
    
// 將 Object 類型轉(zhuǎn)換為 Person (需要類型轉(zhuǎn)換才能成功)
Person person = (Person)books.get(0);
// 但是雖然編譯正確了,運(yùn)行時(shí)還是會(huì)拋出異常 ClassCastException

因此 Java 針對(duì)這一問題就出現(xiàn)了泛型

Java 泛型(generics)是 JDK 5 中引入的一個(gè)新特性,泛型提供了編譯時(shí)類型安全檢測機(jī)制,該機(jī)制允許程序員在編譯時(shí)檢測到非法的類型。

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

1.2 泛型的分類

泛型可以分為兩類

  • 泛型類
  • 泛型方法

預(yù)備知識(shí)主要是為了學(xué)習(xí)、理解集合框架,所以這里只簡單介紹泛型類,后面將會(huì)專門為泛型寫一個(gè)章節(jié)。

1.3 泛型類的定義

規(guī)則:

  • 在類名后面添加了類型參數(shù)聲明
  • 泛型類的類型參數(shù)聲明部分包含一個(gè)或多個(gè)類型參數(shù),參數(shù)間用逗號(hào)隔開。一個(gè)泛型參數(shù),也被稱為一個(gè)類型變量,是用于指定一個(gè)泛型類型名稱的標(biāo)識(shí)符
  • 泛型的泛型參數(shù)一定是類類型,如果是簡單類型,那么必須是對(duì)應(yīng)的包裝類

這里直接將上面定義的 MyArrayList 類改寫成泛型類

示例代碼:

public class MyArrayList<T>{
    private T[] array;
    private int size;
	public MyArrayList(){
        this.array=(T[])new Object[10];
    }
    public void add(T val){
        this.array[size]=val;
        this.size++;
    }
    public T get(int index){
        return this.array[index];
    }
    ...
}

此時(shí)我們就將這個(gè)順序表改寫成了一個(gè)泛型類,接下來我們來使用它

示例代碼:

MyArrayList<String> myArrayList = new MyArrayList<>();
myArrayList.add("Hello");
myArrayList.add("Goodbye");
String s = myArrayList.get(0);
System.out.println(s);
// 結(jié)果為:Hello

上述的 myArrayList 只能存放 String 類型的元素,并且不需要再添加強(qiáng)制類型轉(zhuǎn)換

泛型的意義:

  • 自動(dòng)進(jìn)行類型的檢查
  • 自動(dòng)進(jìn)行類型的轉(zhuǎn)換

Java 中泛型標(biāo)記符: 類型形參一般使用一個(gè)大寫字母表示,如:

  • E — Element(在集合中使用,因?yàn)榧现写娣诺氖窃兀?/li>
  • T — Type(Java 類)
  • K — Key(鍵)
  • V — Value(值)
  • N — Number(數(shù)值類型)
  • ? —表示不確定的 Java 類型

1.4 泛型編譯的機(jī)制

如果不重寫 toString 方法,輸出某個(gè)類的實(shí)例化對(duì)象,如

代碼示例:

// 假設(shè)創(chuàng)建了一個(gè) Person 類
Person person = new Person();
System.out.println(person);

結(jié)果為:

在這里插入圖片描述

如果用上述的泛型類,輸出其實(shí)例化對(duì)象,如

代碼示例:

MyArrayList<String> myArrayList1 = new MyArrayList<>();
System.out.println(myArrayList1);
MyArrayList<Integer> myArrayList2 = new MyArrayList<>();
System.out.println(myArrayList2);
MyArrayList<Boolean> myArrayList3 = new MyArrayList<>();
System.out.println(myArrayList3);

結(jié)果為:

在這里插入圖片描述

我們發(fā)現(xiàn):

泛型類和非泛型類輸出的樣例格式都是一樣的:類名@地址

為什么泛型類的實(shí)例化對(duì)象結(jié)果不是輸出泛型類后面的泛型參數(shù) < T > 呢?

這里就要了解泛型是怎么編譯的

泛型的編譯使用了一種機(jī)制:擦除機(jī)制

擦除機(jī)制只作用于編譯期間,換句話說,泛型就是編譯時(shí)期的一種機(jī)制,運(yùn)行期間沒有泛型的概念

解釋:

  • 當(dāng)我們存放元素的時(shí)候,泛型就會(huì)根據(jù) <T> 自動(dòng)進(jìn)行類型的檢查。
  • 但編譯的時(shí)候,這些 <T> 就被擦除成了 Object

2. 預(yù)備知識(shí)-包裝類(Wrapper Class)

Object 引用可以指向任意類型的對(duì)象,但有例外出現(xiàn)了,8 種基本數(shù)據(jù)類型不是對(duì)象,那豈不是剛才的泛型機(jī)制要失效了?

實(shí)際上也確實(shí)如此,為了解決這個(gè)問題,Java 中引入了一類特殊的類,即這 8 種基本數(shù)據(jù)類型的包裝類。在使用過程中,會(huì)將類似 int 這樣的值包裝到一個(gè)對(duì)象中去。

2.1 基本數(shù)據(jù)類型和包裝類的對(duì)應(yīng)關(guān)系

基本數(shù)據(jù)類型 包裝類
byte Byte
short Short
int Integer
long Long
float Float
double Double
char Character
boolean Boolean

2.2 包裝類介紹

Java 是一個(gè)面向?qū)ο蟮恼Z言,基本類型并不具有對(duì)象的性質(zhì),為了與其他對(duì)象“接軌”就出現(xiàn)了包裝類型

既然包裝類是一個(gè)類,那么就有它對(duì)應(yīng)的成員變量和成員方法。打孔大家可以具體的去查看文檔了解各個(gè)包裝類

2.3 裝箱(boxing)和拆箱(unboxing)

包裝類中有兩個(gè)重要的知識(shí)點(diǎn),裝箱和拆箱

  • 裝箱: 把基本數(shù)據(jù)類型轉(zhuǎn)為對(duì)應(yīng)的包裝類型
  • 拆箱: 把包裝類型轉(zhuǎn)換為基本數(shù)據(jù)類型

裝箱示例代碼:

// 方式一
Integer i1 = 10;
// 方式二
Integer i2 = Integer.valueOf(10);
// 方式三
Integer i3 = new Integer(10);

拆箱示例代碼:

// 方式一
int i = i1;
// 方式二
int i = i1.intValue();

2.4 自動(dòng)裝箱(autoboxing)和自動(dòng)拆箱(autounboxing)

那自動(dòng)裝箱又是什么呢?我們可以對(duì)下面這份代碼進(jìn)行反編譯(反編譯指令為 javap -c 類名

代碼示例:

public class TestDemo {
    public static void main(String[] args) {
        Integer i = 10;
        int j = i;
    }
}

通過反編譯指令,得到了如下結(jié)果:

在這里插入圖片描述

  • 我們發(fā)現(xiàn)在底層中 10 是通過 Integer.valueOf 這個(gè)靜態(tài)方法賦值給了 i,進(jìn)行裝箱操作
  • 再將 i 通過 Integer.intValue 這個(gè)方法復(fù)制給了 j,進(jìn)行拆箱操作

那么什么是手動(dòng)裝箱和手動(dòng)拆箱呢?

就是和底層原理一樣,通過 Integer.valueOfInteger.intValue 方法進(jìn)行的裝箱和拆箱就是手動(dòng)的

而不是通過這些方法進(jìn)行的裝箱和拆箱就是自動(dòng)的

2.5 包裝類面試題

思考下列代碼結(jié)果:

Integer a = 120;
Integer b = 120;
System.out.println(a == b);

結(jié)果為:true

再看一個(gè)代碼:

Integer a = 130;
Integer b = 130;
System.out.println(a == b);

結(jié)果為:false

在這里插入圖片描述

這是為什么呢?

  • 首先我們看到 a 和 b 都進(jìn)行了裝包操作,因此我們就要去了解裝包的時(shí)候發(fā)生了什么
  • 通過轉(zhuǎn)到 Integer.valueOf 的定義我們看到

在這里插入圖片描述

  • 該定義意思就是:如果 i 大于等于 IntegerCache 的最小值,小于它的最大值,就返回 IntegerCache.cache[i + (-IntegerCache.low)] ,否則就返回 new Integer(i)
  • 而 new 一個(gè)對(duì)象的話,相當(dāng)于比較的就是地址的值了,所以是 false
  • 因此我們要知道 IntegerCache 的最大值以及最小值是多少,此時(shí)我們轉(zhuǎn)到它的定義

在這里插入圖片描述

  • 上圖中我們了解到 low 為 -128、high為 127,而 cache 其實(shí)就是一個(gè)數(shù)組。我們知道數(shù)組的下標(biāo)是從 0 開始的,而 i + (-IntegerCache.low) 表示的最小值正好就是 0,也就是說明數(shù)組下標(biāo)為 0 時(shí)存儲(chǔ)的值就為 -128,并且依次往后遞推。
  • 因此數(shù)值在 -128 到 127 之間時(shí)返回的就是和這個(gè)數(shù)相同的值,所以結(jié)果為 true

那為什么要專門創(chuàng)建一個(gè)數(shù)組呢?所有數(shù)字返回 new 的對(duì)象不就行了嗎?

這是因?yàn)?,這樣做可以提高效率。實(shí)例化對(duì)象是需要消耗資源的。而數(shù)組其實(shí)就是一個(gè)對(duì)象,可以減少資源的消耗。

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

相關(guān)文章

  • Mybatis-Plus自動(dòng)生成代碼的實(shí)現(xiàn)示例

    Mybatis-Plus自動(dòng)生成代碼的實(shí)現(xiàn)示例

    在工作中,程序員很多時(shí)候都是在寫類似的代碼,可以使用自動(dòng)生成代碼,本文主要介紹了Mybatis-Plus自動(dòng)生成代碼的實(shí)現(xiàn)示例,具有一定的參考價(jià)值,感興趣的可以了解一下
    2023-11-11
  • java 中Collection存儲(chǔ)器詳解及簡單實(shí)例

    java 中Collection存儲(chǔ)器詳解及簡單實(shí)例

    這篇文章主要介紹了java 中Collection存儲(chǔ)器詳解及簡單實(shí)例的相關(guān)資料,需要的朋友可以參考下
    2017-04-04
  • Spring擴(kuò)展BeanFactoryPostProcessor使用技巧詳解

    Spring擴(kuò)展BeanFactoryPostProcessor使用技巧詳解

    這篇文章主要為大家介紹了Spring擴(kuò)展BeanFactoryPostProcessor使用技巧詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-09-09
  • 解決Mac?m1?電腦?idea?卡頓的問題

    解決Mac?m1?電腦?idea?卡頓的問題

    這篇文章主要介紹了Mac?m1?電腦?idea?卡頓的問題解決,文中給大家補(bǔ)充介紹了IDEA卡頓問題處理方法,需要的朋友可以參考下
    2023-03-03
  • Java中的類初始化解析

    Java中的類初始化解析

    這篇文章主要介紹了Java中的類初始化解析,類的初始化是一個(gè)Java類生命周期中的其中一個(gè)階段,初始化是類加載的最后一個(gè)階段,也正是在初始化階段,才會(huì)真正開始執(zhí)行類中所寫的Java代碼,需要的朋友可以參考下
    2023-08-08
  • 每日六道java新手入門面試題,通往自由的道路

    每日六道java新手入門面試題,通往自由的道路

    這篇文章主要為大家分享了最有價(jià)值的6道java面試題,涵蓋內(nèi)容全面,包括數(shù)據(jù)結(jié)構(gòu)和算法相關(guān)的題目、經(jīng)典面試編程題等,對(duì)hashCode方法的設(shè)計(jì)、垃圾收集的堆和代進(jìn)行剖析,感興趣的小伙伴們可以參考一下
    2021-06-06
  • Java銀行取錢線程安全問題實(shí)例分析

    Java銀行取錢線程安全問題實(shí)例分析

    這篇文章主要介紹了Java銀行取錢線程安全問題,結(jié)合具體實(shí)例形式分析了java使用線程操作模擬銀行取錢的相關(guān)安全問題,需要的朋友可以參考下
    2019-09-09
  • SpringBoot+devtools實(shí)現(xiàn)熱部署的示例代碼

    SpringBoot+devtools實(shí)現(xiàn)熱部署的示例代碼

    在軟件項(xiàng)目的開發(fā)過程中,不可避免的會(huì)經(jīng)常修改代碼,每次修改代碼,都需要手動(dòng)停止然后再啟動(dòng)服務(wù),最后驗(yàn)證代碼的正確性,今天通過這篇文章,我們一起來學(xué)習(xí)一下如何使用Spring?Boot?+?devtools?輕松搞定熱部署,需要的朋友可以參考下
    2024-08-08
  • Java使用get請求接收List集合數(shù)據(jù)(json)并導(dǎo)出報(bào)表問題

    Java使用get請求接收List集合數(shù)據(jù)(json)并導(dǎo)出報(bào)表問題

    這篇文章主要介紹了Java使用get請求接收List集合數(shù)據(jù)(json)并導(dǎo)出報(bào)表問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-11-11
  • java實(shí)現(xiàn)輸入輸出流代碼分享

    java實(shí)現(xiàn)輸入輸出流代碼分享

    這篇文章主要介紹了java實(shí)現(xiàn)輸入輸出流代碼分享的相關(guān)資料,需要的朋友可以參考下
    2015-09-09

最新評(píng)論

神池县| 那曲县| 大理市| 芜湖县| 乌兰县| 密云县| 漳州市| 舞钢市| 独山县| 霍州市| 当涂县| 巢湖市| 浦江县| 塔河县| 法库县| 海晏县| 金秀| 南涧| 盐津县| 沅陵县| 沂南县| 阜新市| 大竹县| 韶关市| 平原县| 安庆市| 鹤壁市| 广宁县| 绥棱县| 邵武市| 化州市| 孟村| 苍梧县| 嘉善县| 新密市| 平遥县| 富锦市| 深圳市| 偏关县| 科技| 昌邑市|