Java詳細(xì)分析講解泛型
1.泛型概念
泛型就是將類(lèi)型參數(shù)化
所謂類(lèi)型參數(shù)化就是將類(lèi)型定義成參數(shù)的形式,然后在使用此類(lèi)型的時(shí)候的時(shí)候再傳入具體的類(lèi)型
到這我們可以看出來(lái):泛型在定義的時(shí)候是不知道具體類(lèi)型的,需要在使用的時(shí)候傳入具體的類(lèi)型,泛型可以用在類(lèi)、接口和方法中,這樣做的好處是一個(gè)泛型可以適用多種情況
2.泛型的使用
2.1泛型類(lèi)語(yǔ)法
public class 類(lèi)名<T> {......}
<T>表示這是一個(gè)泛型類(lèi),T是type的首字母大寫(xiě),除此之外的名稱(chēng)還有:
E:element
K:key
V:vlaue
N:number
<>中可以有多個(gè)類(lèi)型參數(shù),中間使用逗號(hào)隔開(kāi)
2.2泛型方法語(yǔ)法
public<泛型類(lèi)型> 返回值 方法名(泛型類(lèi)型 參數(shù)) {......}
2.3泛型接口語(yǔ)法
public interface 接口名<泛型類(lèi)型> {......}
2.4泛型在main方法中的使用
下面寫(xiě)一個(gè)泛型類(lèi)來(lái)引出后面的內(nèi)容
class Fc<T>{
private T a;
public T get (T data) {
this.a=data;
return a;
}
}前面說(shuō)過(guò)泛型是在使用的時(shí)候再傳入具體的類(lèi)型,所以在實(shí)例化上面泛型類(lèi)的時(shí)候要指定類(lèi)型。具體方式如下
類(lèi)名<具體類(lèi)型>變量名=new 類(lèi)名<具體類(lèi)型>();

注意:
- 等號(hào)右邊<>中可以不寫(xiě)具體類(lèi)型,編譯器可以根據(jù)上下文推導(dǎo)出此處的類(lèi)型
- <>中只能寫(xiě)入類(lèi),所以如果是基本數(shù)據(jù)類(lèi)型,就需要寫(xiě)入其對(duì)應(yīng)的包裝類(lèi),包裝類(lèi)除int是Integer,char包裝類(lèi)是Character外,其余均是首字母大寫(xiě)
- Java中不能創(chuàng)建泛型數(shù)組,至于原因要從Java中泛型的機(jī)制說(shuō)起
3.擦除機(jī)制
Java實(shí)現(xiàn)泛型是依靠這個(gè)擦除機(jī)制的,這個(gè)機(jī)制目前來(lái)講過(guò)于復(fù)雜,只說(shuō)結(jié)果
Java編譯器在編譯的時(shí)候會(huì)去掉類(lèi)型參數(shù),而對(duì)于泛型類(lèi)型來(lái)說(shuō),如果指定上界會(huì)用上界類(lèi)型進(jìn)行替換,沒(méi)有指定上界則會(huì)以O(shè)bject來(lái)進(jìn)行替換
所以在編譯的時(shí)候泛型類(lèi)型都被替換成了Object,編譯后的class文件是不包含任何泛型信息的,即泛型信息不會(huì)進(jìn)入到運(yùn)行時(shí)階段
但Java的數(shù)組需要進(jìn)行運(yùn)行期類(lèi)型檢查,而由于類(lèi)型擦除,造成數(shù)組運(yùn)行期類(lèi)型檢查不能正常進(jìn)行,破壞了Java數(shù)組運(yùn)行期類(lèi)型檢查的機(jī)制
4.泛型的上界
所謂泛型的上界就是對(duì)傳入的類(lèi)型變量進(jìn)行約束,指定哪些類(lèi)型可以傳入,哪些不行,語(yǔ)法如下:
class 類(lèi)名<類(lèi)型參數(shù)extends類(lèi)型邊界> {......}
還是以上面的泛型類(lèi)為例,現(xiàn)在改成如下情況:
class Fc<E extends Number >{
private E a;
public E get (E data) {
this.a=data;
return a;
}
}那么此時(shí)Fc就只能傳入Number或者其子類(lèi)

5.通配符
通配符就是“?”在泛型中使用,它是用來(lái)解決泛型無(wú)法協(xié)變的問(wèn)題,那什么是協(xié)變?
假設(shè)有兩個(gè)類(lèi)A和B,A繼承B,那么泛型Fc<A>應(yīng)該也是Fc<B>的子類(lèi),但泛型不支持這樣的父子關(guān)系
基于上面的情況,所以需要使用通配符
直接寫(xiě)兩個(gè)類(lèi),A繼承B
class B {
}
class A extends B {
}

現(xiàn)在把<B>改成<?>

5.1通配符的上界
通配符也可以指定界限,語(yǔ)法和泛型的上界類(lèi)似
<? extends 類(lèi)型邊界>
假設(shè)<? extends Number>,那么可以傳入的是Number及其子類(lèi)
但需要注意的是:通配符的上界只能用來(lái)讀取數(shù)據(jù),不能用來(lái)寫(xiě)入數(shù)據(jù)
因?yàn)槲覀冎恢览锩婵梢詡魅胧裁搭?lèi)型的數(shù)據(jù),但具體是什么類(lèi)型我們不知道,所以也就無(wú)法對(duì)數(shù)據(jù)進(jìn)行修改,但是讀取則可以直接用父類(lèi)對(duì)象來(lái)進(jìn)行接收讀取出來(lái)的數(shù)據(jù)
5.2通配符的下界
下界使用的是super
<? super 類(lèi)型邊界>
<? super Integer>表示可以傳入Integer或者其父類(lèi)
通配符下界可以進(jìn)行寫(xiě)入數(shù)據(jù),但不能用來(lái)讀取數(shù)據(jù)
原因也很簡(jiǎn)單,里面可以傳的類(lèi)都是Integer或者它的父類(lèi),寫(xiě)進(jìn)去的數(shù)據(jù)可以進(jìn)行轉(zhuǎn)化,但讀取數(shù)據(jù)用哪一個(gè)父類(lèi)對(duì)象接收則不好確定了
6.包裝類(lèi)
由于Java中基本數(shù)據(jù)類(lèi)型不是繼承Object類(lèi),所以為了泛型能夠支持基本數(shù)據(jù)類(lèi)型,每一個(gè)基本數(shù)據(jù)類(lèi)型都有各自的包裝類(lèi)
| 基本數(shù)據(jù)類(lèi)型 | 包裝類(lèi) |
| byte | Byte |
| short | Short |
| int | Integer |
| long | Long |
| float | Float |
| double | Double |
| char | Character |
| boolean | Boolean |
6.1裝箱和拆箱
裝箱就是把基本數(shù)據(jù)類(lèi)型改為對(duì)應(yīng)的包裝類(lèi)類(lèi)型,拆箱就是和裝箱相反的操作
Java中提供了自動(dòng)裝箱和拆箱機(jī)制,但還是先來(lái)看下手動(dòng)裝箱和拆箱的操作
//手動(dòng)裝箱 int i=10; Integer j=Integer.valueOf(i); //第一種操作 Integer j=new Integer(i); //第二種操作 //手動(dòng)拆箱 int a=j.intValue();
自動(dòng)裝箱和拆箱的話代碼就要少的多
int i=10; Integer j=i; //自動(dòng)裝箱 int a=j; //自動(dòng)拆箱
關(guān)于int的包裝類(lèi)有一個(gè)比較有趣的地方,裝箱使用了valueOf方法,其源碼如下:

可以看到傳給方法的參數(shù)首先是和IntegerCache進(jìn)行比較,如果參數(shù)的值是在某個(gè)范圍中,那么返回的是數(shù)組里面的元素,否則返回新的對(duì)象
那我們來(lái)看看這個(gè)IntegerCache

也就是說(shuō)-128<=i<=127的時(shí)候返回的是類(lèi)中的數(shù)組的元素,那么就會(huì)有一個(gè)情況如下:

原因和上面所講一樣
泛型結(jié)束,后面數(shù)據(jù)結(jié)構(gòu)的時(shí)間復(fù)雜度和空間復(fù)雜度這兩個(gè)概念就不寫(xiě)了,下一篇直接到順序表
到此這篇關(guān)于Java詳細(xì)分析講解泛型的文章就介紹到這了,更多相關(guān)Java泛型內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
springboot整合mybatis將sql打印到日志的實(shí)例詳解
這篇文章主要介紹了springboot整合mybatis將sql打印到日志的實(shí)例詳解,需要的朋友可以參考下2017-12-12
Java多線程之volatile關(guān)鍵字及內(nèi)存屏障實(shí)例解析
volatile是JVM提供的一種最輕量級(jí)的同步機(jī)制,因?yàn)镴ava內(nèi)存模型為volatile定義特殊的訪問(wèn)規(guī)則,使其可以實(shí)現(xiàn)Java內(nèi)存模型中的兩大特性:可見(jiàn)性和有序性。這篇文章主要介紹了Java多線程之volatile關(guān)鍵字及內(nèi)存屏障,需要的朋友可以參考下2019-05-05
java中字符進(jìn)行全角半角轉(zhuǎn)換示例代碼
全角:指一個(gè)字符占用兩個(gè)標(biāo)準(zhǔn)字符位置,而半角:指一字符占用一個(gè)標(biāo)準(zhǔn)的字符位置,在日常開(kāi)發(fā)中經(jīng)常會(huì)遇到全角半角轉(zhuǎn)換的要求,下面這篇文章主要給大家介紹了關(guān)于java中字符進(jìn)行全角半角轉(zhuǎn)換的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考下。2017-08-08
feign調(diào)用第三方接口,編碼定義GBK,響應(yīng)中文亂碼處理方式
這篇文章主要介紹了feign調(diào)用第三方接口,編碼定義GBK,響應(yīng)中文亂碼處理方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-01-01
Java ScheduledExecutorService的具體使用
ScheduledExecutorService有線程池的特性,也可以實(shí)現(xiàn)任務(wù)循環(huán)執(zhí)行,本文主要介紹了Java ScheduledExecutorService的具體使用,具有一定的參考價(jià)值,感興趣的可以了解一下2023-05-05
Mybatis-Plus中IdType.AUTO局部配置不生效的問(wèn)題解決
本文主要介紹了Mybatis-Plus中IdType.AUTO局部配置不生效的問(wèn)題解決,數(shù)據(jù)庫(kù)插入數(shù)據(jù)時(shí),id的默認(rèn)生成方式還是雪花算法,局部配置沒(méi)有生效,下面就來(lái)解決一下,感興趣的可以了解一下2023-09-09

