泛型數據java基礎,但真正理解需要悉心品嘗。畢竟在工作中用到的是在是太多了。
不要以為new arraylist<>這就是泛型,這只能屬于會使用。
在工作中,相對于現有的項目源碼的數據庫操作層,無論是mybatis,hibernate或者是自己封裝的basemodel層,都會使用到泛型。
以及<? extends t> 和 <? super t>這個屌東西。
泛型使用情況分為三類
1. 泛型類。
2. 泛型方法。
3. 泛型接口。
出于規范的目的,java 還是建議我們用單個大寫字母來代表類型參數。常見的如:
1. t 代表一般的任何類。
2. e 代表 element 的意思,或者 exception 異常的意思。
3. k 代表 key 的意思。
4. v 代表 value 的意思,通常與 k 一起配合使用。
5. s 代表 subtype 的意思,文章后面部分會講解示意。
最直接的一段代碼。
1
2
3
|
list<string> l1 = new arraylist<string>(); list<integer> l2 = new arraylist<integer>(); system.out.println(l1.getclass() == l2.getclass()); |
打印的判斷為true,因為泛型信息被擦除了。
泛型擦除實例。
1
2
3
4
5
6
7
8
9
|
list<string> listerasure = new arraylist<string>() { // 直接初始化,這也是一種方式。直接傳入一個collection。 {add( "aaa" );add( "bbb" );} }; listerasure.add( "ccc" ); class <? extends list> class1 = listerasure.getclass(); method method = class1.getmethod( "add" ,object. class ); method.invoke(listerasure, 123 ); system.out.println(listerasure) |
輸出結果 [aaa, bbb, ccc, 123]
明明是接收string類型,但是卻可以通過反射對其進行integer類型的操作。
可見泛型只是在編譯期間有效。
<?> 代表著類型未知
<? extends t> 和 <? super t>這個東西經常見到,但是并沒有字面意義那么簡單。
通配符有 3 種形式。
- <?> 被稱作無限定的通配符。
- <? extends t> 被稱作有上限的通配符。
- <? super t> 被稱作有下限的通配符。
1
2
3
|
class a{} class b extends a{} class c extends b{} |
1
2
3
4
5
6
7
8
9
10
|
list<? extends b> listextends = new arraylist<b>(); // listextends.add(new a()); 全部編譯錯誤。因為使用的是extends,喪失了寫的操作能力。跟f3方法一樣,是未知類型,只是確定了里面對象的范圍。是b的子類。 // listextends.add(new b()); // listextends.add(new c()); // 能進行對b以及b的子類操作。這是super的神奇之處。 list<? super b> listsuper = new arraylist<b>(); // listsuper.add(new a());//會編譯錯誤。 listsuper.add( new b()); listsuper.add( new c()); |
以及方法泛型的返回
泛型作為參數的傳遞。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
public static <ttt>ttt f1(ttt t) { return t; } // 傳遞指定的a類型,對應的list可以進行對應的list應有的方法。 public static void f2(list<a> list) { list.add( new a()); system.out.println(list.size()); } public static void f3(list<?> list) { // list.add(new a()); //當傳入的是?通配符的話表示只能進行跟?無關的操作,類似于size方法,增加代碼的可讀性。 system.out.println(list.size()); } public static void f4(list<? extends b> listextends) { // listextends.add(new b());//不能進行寫做操,因為是?,增加了可讀性。 system.out.println(listextends.size()); } |
測試代碼,很全面
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
|
package com.javase.fanxing; import java.lang.reflect.invocationtargetexception; import java.lang.reflect.method; import java.util.arraylist; import java.util.list; class a{} class b extends a{} class c extends b{} public class demo<t,tt> { t value; tt value2; public tt getvalue2() { return value2; } public void setvalue2(tt value2) { this .value2 = value2; } public t getvalue() { return value; } public void setvalue(t value) { this .value = value; } public static <ttt>ttt f1(ttt t) { return t; } // 傳遞指定的a類型,對應的list可以進行對應的list應有的方法。 public static void f2(list<a> list) { list.add( new a()); system.out.println(list.size()); } public static void f3(list<?> list) { // list.add(new a()); //當傳入的是?通配符的話表示只能進行跟?無關的操作,類似于size方法,增加代碼的可讀性。 system.out.println(list.size()); } public static void f4(list<? extends b> listextends) { // listextends.add(new b());//不能進行寫做操,因為是?,增加了可讀性。 system.out.println(listextends.size()); } public static void main(string[] args) throws nosuchmethodexception, securityexception, illegalaccessexception, illegalargumentexception, invocationtargetexception, instantiationexception { // 打印的判斷為true,因為泛型信息被擦除了。 list<string> l1 = new arraylist<string>(); list<integer> l2 = new arraylist<integer>(); system.out.println(l1.getclass() == l2.getclass()); // 泛型擦除實例。 list<string> listerasure = new arraylist<string>() { // 直接初始化,這也是一種方式。直接傳入一個collection。 {add( "aaa" );add( "bbb" );} }; listerasure.add( "ccc" ); class <? extends list> class1 = listerasure.getclass(); method method = class1.getmethod( "add" ,object. class ); method.invoke(listerasure, 123 ); system.out.println(listerasure); demo<string,integer> demo = new demo<string,integer>(); demo.setvalue( "string" ); system.out.println(demo.getvalue()); demo<integer,string> demo2 = new demo<integer,string>(); demo2.setvalue( 100 ); system.out.println(demo2.getvalue()); system.out.println(f1( 123 )); // list<a> lista = new arraylist<a>(); // list<b> listb = lista;//new arraylist<b>();雖然b是a的子類,并不代表泛型之間也具備繼承關系。 arraylist<a> lista = new arraylist<a>(); lista.add( new a()); f3(lista); // 不對f3方法進行任何操作,是1. f2(lista); // 2對應的方法實現還進行了一次插入操作。 f3(lista); // static ,對應的lista的集合數量是引用值。 arraylist<b> listb = new arraylist<b>(); listb.add( new b()); f3(listb); // f3方法傳遞的是通配符?,不能進行add操作。 // <? extends t> 和 <? super t> list<? extends b> listextends = new arraylist<b>(); // listextends.add(new a()); 全部編譯錯誤。因為使用的是extends,喪失了寫的操作能力。跟f3方法一樣,是未知類型,只是確定了里面對象的范圍。是b的子類。 // listextends.add(new b()); // listextends.add(new c()); // 能進行對b以及b的子類操作。這是super的神奇之處。 list<? super b> listsuper = new arraylist<b>(); // listsuper.add(new a());//會編譯錯誤。 listsuper.add( new b()); listsuper.add( new c()); // 沒毛病。 list<b> listbs = new arraylist<b>(); listbs.add( new b()); f4(listbs); } } |
原文鏈接:https://www.cnblogs.com/c-h-y/p/9465040.html