java中的single_解析java泛型(一)
對于我們java中的泛型,可能很多人知道怎么使用并且使用的還不錯,但是我認為想要恰到好處的使用泛型,還是需要深入的了解一下它的各種概念和內(nèi)部原理。本文將盡可能的囊括java泛型中的重要的概念。主要內(nèi)容如下:泛型的定義及為什么要使用泛型
定義一個簡單的泛型類
定義一個簡單的泛型方法
類型參數(shù)的限定
泛型內(nèi)部實現(xiàn)的基本原理
泛型通配符(難點)
泛型的其他實現(xiàn)細節(jié)
一、何謂泛型
泛型程序設計意味著編寫的代碼可以被不同中類型的對象重用。例如:MyList,MyList是一種類型,MyList也是一種類型,但是使用的代碼塊都是MyList,這也就是java中引入泛型的一種原因:可以增強代碼的復用性,當然這種限定死類型的方式也會使得代碼的安全性和可讀性更高。
二、一個簡單的泛型類
先看一個完整的泛型類:/*一個簡單的泛型類的聲明如下*/
public class Pair {
private T a;
private T b;
public Pair(T a, T b){
this.a = a;
this.b = b;
}
}
由此可以看出來,泛型類型和普通類型的區(qū)別主要在于:類名之后多了個,并且實例域類型可以不是具體的類型而是不確定的T類型。其中,我們管T叫做類型變量,類型變量一般使用大寫字母表示并且很短(在java中使用E表示集合的元素類型,K和V分別表示關鍵字和值的類型)。
使用具體的類型來替換類型變量的過程我們叫做實例化泛型類型。例如:Pair,等。這其中需要注意的是:java中的9中基本類型是不能作為類型變量的,也就是:Pair,是會不允許的。當然,聲明一個泛型類時,不局限于一個類型變量,可以由多個類型變量,例如:/*聲明兩個類型變量也是可以的*/
public class Pair {
private T a;
private U b;
public Pair(T a, U b){
this.a = a;
this.b = b;
}
}
//Pair p new Pair<>("abc",12);
//創(chuàng)建泛型類實例變量的時候,可以省略類型變量,編譯器可以推測出來
三、一個簡單的泛型方法
怎么定義泛型類,我們已經(jīng)介紹過了,接下來我們一起看看泛型方法是如何定義和調(diào)用的。/*泛型類中定義了一個泛型方法*/
public class Pair {
//聲明一個泛型方法
public T getA(T c){
return c;
}
}
/*main函數(shù)中調(diào)用泛型方法*/
public class Test2 {
public static void main(String[] args){
Pair p = new Pair(1,2);
//調(diào)用泛型方法
System.out.println(p.show(10));
}
}
我們可以看到,聲明一個泛型方法:public T getA(T c),放在返回值前面,修飾符后面,T表示返回類型。泛型方法的調(diào)用:p.show(10),在方法名前面放置類型變量,當然也可以選擇省略,當編譯器沒有足夠的信息推測出來時就會報錯,那時你再添加也不遲(但是,如果你能減輕計算機的工作的話,想必是可以提高效率的)
小結一下,泛型類和泛型方法。泛型類中可以聲明泛型方法也可以聲明普通方法,泛型方法可以出現(xiàn)在泛型類中也可以出現(xiàn)在普通類中,也就是它們之間并沒有什么約束關系。四、類型變量的限定
前面我們已經(jīng)知道了什么是類型變量,我們看一段代碼:public class Pair {
public static int myCompare(T a,T b){
return a.compareTo(b);//此處編譯不通過
}
}
我們知道,如果想要使用compareTo方法,就要實現(xiàn)Comparable接口,或者繼承實現(xiàn)了此接口的類。此處想要使得程序正確,有兩種辦法。第一種:使類繼承Comparable接口并且實現(xiàn)compareTo方法。第二種:就是使用類型變量限定。如下:/*限定變量類型*/
public class Pair {
public static int myCompare(T a,T b){
return a.compareTo(b);
}
}
細心的同學可能已經(jīng)發(fā)現(xiàn),相比于原來的方法,就是使類型變量繼承與Comparable接口。原來的變成了,表示:原來的T可以是任意類型的,而現(xiàn)在的T被限制必須實現(xiàn)了Comparable 接口,就是說,凡是使用此泛型的類都是直接或者間接繼承了Comparable 接口并實現(xiàn)其中方法的。所以,一旦我們將T限定了,就不用考慮實現(xiàn)Comparable 接口的事情了,程序的封裝性更強了。
對類型變量的限定可以由多個限定,它們之間使用&分隔,而使用逗號分隔類型變量。看個例子:
//一個類型變量的一個類型限定
//一個類型變量的兩個類型限定
//兩個類型變量的類型限定
五、泛型實現(xiàn)的基本原理
討論了這么多的泛型方法,泛型類以及各種使用技巧,接下來,我們一起看看虛擬機實際執(zhí)行時是怎么對待我們的泛型的。我們都知道java中有編譯器和虛擬機,但實際上我們的泛型在這兩者看來是不一樣的,也就是說,虛擬機是不認識泛型的,而只有我們強大的編譯器是認識泛型的。那他們是怎么實現(xiàn)統(tǒng)一的呢?接下來我們詳細來看。
在java中,無論何時定義了一個泛型,它都會自動生成一個相應的原始類型。我們叫這個過程為:類型擦除。例如下面的代碼:/*這是一段泛型類的代碼*/
public class Pair {
private T a;
private T b;
public T getA(){
return this.a;
}
public T getB(){
return this.b;
}
}
經(jīng)過類型擦除之后生成原始類型:
public class Pair{
private Object a;
private Object b;
public Object getA(){
return this.a;
}
public Object getB(){
return this.b;
}
}
經(jīng)過對比,我們可以得出結論:去除了泛型的標志性符號<>并且所有的T類型都被替換成Object類型了。難道我們的類型擦除就是將所有的未知類型轉換為Object類型嗎?當然不是,類型擦除是有規(guī)則的而不是一味的將未知類型T轉換成Object類型的。
對于有限定的類型變量就將用類型變量的第一個限定類型替換。如:Pair,就會選擇用Comparable替換所有的T并去除修飾在類后面的泛型符號,生成原始類型。
對于沒有限定類型的類型變量就默認使用Object替換類型變量。例如:Pair就會使用Object替換所有的T類型變量。
最后小結一下,類型擦除針對是否有類型限定類型,根據(jù)不同的狀況進行替換生成相應的原始類型供jvm調(diào)用。未完,待續(xù)。。。。
總結
以上是生活随笔為你收集整理的java中的single_解析java泛型(一)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 含枚举类型的函数声明_02Golang基
- 下一篇: 关于python序列类型的通用操作符_P