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