JAVA泛型萬用字元T,E,K,V區別,T以及Class<T>,Class<?>的區別

作者:程式魚

連結:https://www。jianshu。com/p/95f349258afb

1。 先解釋下泛型概念

泛型是Java SE 1。5的新特性,泛型的本質是引數化型別,也就是說所操作的資料型別被指定為一個引數。這種引數型別可以用在類、介面和方法的建立中,分別稱為泛型類、泛型介面、泛型方法。Java語言引入泛型的好處是安全簡單。

在Java SE 1。5之前,沒有泛型的情況的下,透過對型別Object的引用來實現引數的“任意化”,“任意化”帶來的缺點是要做顯式的強制型別轉換,而這種轉換是要求開發者對實際引數型別可以預知的情況下進行的。對於強制型別轉換錯誤的情況,編譯器可能不提示錯誤,在執行的時候才出現異常,這是一個安全隱患。

泛型的好處是在編譯的時候檢查型別安全,並且所有的強制轉換都是自動和隱式的,以提高程式碼的重用率。

以上內容摘自百度百科

舉個栗子:

Box類定義為一個泛型類

public

class

Box

<

T

>

{

private

T

object

public

void

set

(T

object

) {

this

object

=

object

; }

public

T

get

() {

return

object

; }

}

建立一個Box物件,不帶泛型引數,發現獲取物件的時候需要強制轉換

Box box2 =

new

Box();

box2。

set

new

Apple());

Apple apple = (Apple) box2。

get

();

建立一個Box物件,帶泛型引數,獲取物件的時候就不需要強制轉換

Box box =

new

Box();

box。

set

new

Apple());

Apple apple = box。

get

();

總結下泛型的好處就是

省去了強制轉換,可以在編譯時候檢查型別安全,可以用在類,方法,介面上

但是我們定義泛型類,泛型方法,泛型介面的時候經常會碰見很多不同的萬用字元T,E,K,V等等,這些萬用字元又都是什麼意思呢?繼續往下看

2。 下來說說泛型萬用字元T,E,K,V區別

這些全都屬於java泛型的萬用字元,剛開始我看到這麼多萬用字元,一下暈了,這幾個其實

沒什麼區別

,只不過是一個約定好的程式碼,也就是說

使用大寫字母A,B,C,D……X,Y,Z定義的,就都是泛型,把T換成A也一樣,這裡T只是名字上的意義而已

表示不確定的java型別

T (type)

表示具體的一個java型別

K V (key value)

分別代表java鍵值中的Key Value

E (element)

代表Element

舉個栗子:

public

class

Test

{

public

List

list

=

new

ArrayList();

public

static

void

main

(String[] args)

{

Test test =

new

Test();

test。

list

。add(

“hello”

);

System。out。println(test。

list

);

}}

public

class

Test

{

public

List

list

=

new

ArrayList();

public

static

void

main

(String[] args)

{

Test test =

new

Test();

test。

list

。add(

“hello”

);

System。out。println(test。

list

);

}}

將T換成了A,在執行效果上是沒有任何區別的,只不過我們約定好了T代表type,所以還是

按照約定規範來比較好

,增加了程式碼的可讀性。

如果要定義

多個

泛型引數,比如說兩個泛型引數

很典型的一個栗子是Map的key,value泛型,我們也可以定義一個這樣的

public

interface

Mymap

<

K

V

>

{

public

K

getKey

()

public

V

getValue

()

}

public

class

MymapImpl

<

K

V

>

implements

Mymap

<

K

V

>

{

private

K key;

private

V value;

public

MymapImpl

(K key, V value)

{

this

。key = key;

this

。value = value;

}

public

K

getKey

()

{

return

key; }

public

V

getValue

()

{

return

value; }

}

下來就可以傳入任意型別,建立例項了,不用轉化型別

Mymap<

String

Integer

> mp1=

new

MymapImpl<

String

Integer

>(

“Even”

8

);

Mymap<

String

String

> mp2=

new

MymapImpl<

String

String

>(

“hello”

“world”

);

Mymap<

Integer

Integer

> mp3=

new

MymapImpl<

Integer

Integer

>(

888

888

);

如果要定義

超過兩個,三個或三個以上

的泛型引數可以使用

T1, T2, …, Tn

,像這樣子

public

class

Test

{

public

void

print

(T1 t1,T2 t2,T3 t3)

{

System。out。println(t1。getClass());

System。out。println(t2。getClass());

System。out。println(t3。getClass());

}

}

3。 接下來說說Object ? T區別

ArrayList

al=new ArrayList

();指定集合元素只能是T型別

ArrayList al=new ArrayList();集合元素可以是任意型別,這種沒有意義,一般是方法中,只是為了說明用法

ArrayList al=new ArrayList();

泛型的限定:

? extends E:接收E型別或者E的子型別。

? super E:接收E型別或者E的父型別

Object和T不同點在於,Object是一個實打實的類,並沒有泛指誰,而T可以泛指Object,比方

public void printList(Listlist){}

方法中可以傳入

List list型別引數,也可以傳入Listlist型別引數,但是public void printList(List list){}就只可以傳入List list型別引數,因為Object型別並沒有泛指誰,是一個確定的型別?和T區別是?是一個不確定類,?和T都表示不確定的型別 ,但如果是T的話,函數里面可以對T進行操作,比方 T car = getCar(),而不能用?car = getCar()。

Listlist