Java中的泛型方法


Java中的泛型方法

 

       泛型是什么意思在這就不多說了,而Java中泛型類的定義也比較簡單,例如:public class Test<T>{}。這樣就定義了一個泛型類Test,在實例化該類時,必須指明泛型T的具體類型,例如:Test<Object> t = new Test<Object>();,指明泛型T的類型為Object。

       但是Java中的泛型方法就比較復雜了。

       泛型類,是在實例化類的時候指明泛型的具體類型;泛型方法,是在調用方法的時候指明泛型的具體類型。

 

       定義泛型方法語法格式如下:

      

       調用泛型方法語法格式如下:

 

       說明一下,定義泛型方法時,必須在返回值前邊加一個<T>,來聲明這是一個泛型方法,持有一個泛型T,然后才可以用泛型T作為方法的返回值。

       Class<T>的作用就是指明泛型的具體類型,而Class<T>類型的變量c,可以用來創建泛型類的對象。

       為什么要用變量c來創建對象呢?既然是泛型方法,就代表着我們不知道具體的類型是什么,也不知道構造方法如何,因此沒有辦法去new一個對象,但可以利用變量c的newInstance方法去創建對象,也就是利用反射創建對象。

       泛型方法要求的參數是Class<T>類型,而Class.forName()方法的返回值也是Class<T>,因此可以用Class.forName()作為參數。其中,forName()方法中的參數是何種類型,返回的Class<T>就是何種類型。在本例中,forName()方法中傳入的是User類的完整路徑,因此返回的是Class<User>類型的對象,因此調用泛型方法時,變量c的類型就是Class<User>,因此泛型方法中的泛型T就被指明為User,因此變量obj的類型為User。

       當然,泛型方法不是僅僅可以有一個參數Class<T>,可以根據需要添加其他參數。

       為什么要使用泛型方法呢?因為泛型類要在實例化的時候就指明類型,如果想換一種類型,不得不重新new一次,可能不夠靈活;而泛型方法可以在調用的時候指明類型,更加靈活。

 

 

http://wwwiteye.iteye.com/blog/1849917

泛型接口

泛型也可以應用於接口,例如生成器,一種專門負責創建對象的類。這其實是工廠方法設計模式的一種應用。不過使用生成器創建對象時,不需要參數。而工廠方法一般是需要參數的。

Java代碼    收藏代碼
  1. package tik4.generic;  
  2.   
  3. public interface Generator<T> {  
  4.     T next();  
  5. }  

 一個Fibonacci數列實現

Java代碼    收藏代碼
  1. package tik4.generic;  
  2.   
  3. public class Fibonacci implements Generator<Integer> {  
  4.     private int count;  
  5.   
  6.     // 參數類型用Integer,使用int將不能編譯  
  7.     // public int next() {  
  8.     // return 0;  
  9.     // }  
  10.     public Integer next() {  
  11.         return fib(count++);  
  12.     }  
  13.   
  14.     private int fib(int n) {  
  15.         if (n < 2return 1;  
  16.         return fib(n - 2) + fib(n - 1);  
  17.     }  
  18.   
  19.     public static void main(String[] args) {  
  20.         Fibonacci gen = new Fibonacci();  
  21.         for (int i = 0; i <= 17; i++)  
  22.             System.out.print(gen.next() + " ");  
  23.     }  
  24.     /* 
  25.      * Output: 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 
  26.      */  
  27. }  

 

泛型方法

可以在類中包含參數化方法,而這個方法所在的類可以是泛型類,也可以不是泛型類。是否擁有泛型方法,和所在的類是否泛型沒有關系。泛型方法使得該方法能夠獨立於類而產生變化。以下是一個基本原則:如果泛型方法可以取代整個類的泛型化,就應該只使用泛型方法。另外,對於一個static方法而言,無法訪問泛型

類的參數類型,所以static方法需要使用泛型能力,就必須成為泛型方法

Java代碼    收藏代碼
  1. package tik4.generic;  
  2.   
  3. public class GenericMothod {  
  4.     public <T,M,N> void getTType(T t,M m,N n){  
  5.         /* 
  6.          * 傳入int,long ,double等基本類型時,自動打包機制 
  7.          * 會將基本類型包裝成相應的對象 
  8.          */  
  9.         System.out.println(t.getClass().getName());  
  10.         System.out.println(m.getClass().getName());  
  11.         System.out.println(n.getClass().getName());  
  12.     }  
  13.     public static void main(String[] args) {  
  14.         //泛型類在創建對象時必須指定參數類型,而泛型方法則不需要在創建對象時指定參數類型T  
  15.         GenericMothod gm = new GenericMothod();  
  16.         gm.getTType(""11.0);  
  17.         gm.getTType(1.0F, 'c', gm);  
  18.     }/* 
  19.      *Output:  
  20.     java.lang.String 
  21.     java.lang.Integer 
  22.     java.lang.Double 
  23.     java.lang.Float 
  24.     java.lang.Character 
  25.     tik4.generic.GenericMothod 
  26.     */  
  27. }  

 

利用參數類型推斷

問題:很煩這種寫法是不是,老子在聲明變量的的時候已經指明了參數類型,為毛還要在初始化對象時再指定?

Java代碼    收藏代碼
  1. Map<Integer, List<? extends Set<String>>> map =   
  2.     new HashMap<Integer, List<? extends Set<String>>>();  

解決:搞一個工具類

Java代碼    收藏代碼
  1. package tik4.generic;  
  2.   
  3. import java.util.HashMap;  
  4. import java.util.List;  
  5. import java.util.Map;  
  6. import java.util.Set;  
  7.   
  8. public class New {  
  9.     public static <K, V> Map<K, V> hashMap() {  
  10.         return new HashMap<K, V>();  
  11.     }  
  12.   
  13.     public static void main(String[] args) {  
  14.         Map<Integer, List<? extends Set<String>>> map = New.hashMap();  
  15.     }  
  16. }  

 注意:

類型推斷只對賦值操作有效,其他時候不起作用。如果你使用泛型方法調用的結果(例如:New.hashMap())作為參數,傳遞給其他方法,此時編譯器不會執行類型推斷。編譯器認為,調用泛型方法之后,其返回值被賦給一個Object類型的變量。上代碼:

Java代碼    收藏代碼
  1. package tik4.generic;  
  2.   
  3. import java.util.List;  
  4. import java.util.Map;  
  5. import java.util.Set;  
  6.   
  7. public class LimitsOfInference {  
  8.     static void f(Map<Integer, List<? extends Set<String>>> map){};  
  9.     public static void main(String[] args) {  
  10.         /* 
  11.          * the mothed f(Map<Integer, List<? extends Set<String>>> 
  12.          * is not applicable for arguments (Map<Object,Object>) 
  13.          * 不能編譯 
  14.          */  
  15. //      f(New.hashMap());  
  16.     }  
  17. }  
 
顯示類型說明?? think in java4中是這么寫的,但是我的機器上不能編譯,難道書上是在扯淡

 在泛型方法中,可以顯示的指定參數類型。在 點操作符 和 方法名之間插入尖括號,然后將類型置於括號內。如果是在定義該方法的類的內部,則在點操作符之前使用this關鍵字如果使用static方法,必須在點操作符之前加上類名。這種語法,可以解決LimitsOfInference.java中的問題。

Java代碼    收藏代碼
  1. package tik4.generic;  
  2.   
  3. import java.util.List;  
  4. import java.util.Map;  
  5. import java.util.Set;  
  6.   
  7. public class ExplicitTypeSpecification {  
  8.     static void f(Map<Integer, String> map){};  
  9.       
  10.     public static void main(String[] args) {  
  11.                 //java 5和java6 中均不能編譯。  
  12.         f(New.<Map<Integer, String>>hashMap());   
  13.     }  
  14. }  

 

 泛型推導在java7中已經實現了。

Java代碼    收藏代碼
  1. List<String> list = new ArrayList<>();  

     因為編譯器可以從前面(List)推斷出推斷出類型參數,所以后面的ArrayList之后可以不用寫泛型參數了,只用一對空着的尖括號就行。當然,你必須帶着”菱形”<>,否則會有警告的。 

     Java SE7 只支持有限的類型推斷:只有構造器的參數化類型在上下文中被顯著的聲明了,你才可以使用類型推斷,否則不行。 看代碼:

Java代碼    收藏代碼
  1. List<String> list = new ArrayList<>();  
  2. list.add("A");  
  3.   
  4. //這個不行  
  5. list.addAll(new ArrayList<>());  
  6.   
  7. // 這個可以  
  8. List<? extends String> list2 = new ArrayList<>();  
  9. list.addAll(list2);  




Java泛型--泛型應用--泛型接口、泛型方法、泛型數組、泛型嵌套

1、泛型接口

1.1泛型接口的基本概念

1.2泛型接口實現的兩種方式

定義子類:在子類的定義上也聲明泛型類型
interface Info<T>{		// 在接口上定義泛型
	public T getVar() ;	// 定義抽象方法,抽象方法的返回值就是泛型類型
}
class InfoImpl<T> implements Info<T>{	// 定義泛型接口的子類
	private T var ;				// 定義屬性
	public InfoImpl(T var){		// 通過構造方法設置屬性內容
		this.setVar(var) ;	
	}
	public void setVar(T var){
		this.var = var ;
	}
	public T getVar(){
		return this.var ;
	}
};
public class GenericsDemo24{
	public static void main(String arsg[]){
		Info<String> i = null;		// 聲明接口對象
		i = new InfoImpl<String>("李興華") ;	// 通過子類實例化對象
		System.out.println("內容:" + i.getVar()) ;
	}
};
如果現在實現接口的子類不想使用泛型聲明,則在實現接口的時候直接指定好其具體的操作類型即可:
interface Info<T>{		// 在接口上定義泛型
	public T getVar() ;	// 定義抽象方法,抽象方法的返回值就是泛型類型
}
class InfoImpl implements Info<String>{	// 定義泛型接口的子類
	private String var ;				// 定義屬性
	public InfoImpl(String var){		// 通過構造方法設置屬性內容
		this.setVar(var) ;	
	}
	public void setVar(String var){
		this.var = var ;
	}
	public String getVar(){
		return this.var ;
	}
};
public class GenericsDemo25{
	public static void main(String arsg[]){
		Info i = null;		// 聲明接口對象
		i = new InfoImpl("李興華") ;	// 通過子類實例化對象
		System.out.println("內容:" + i.getVar()) ;
	}
};

2、泛型方法

2.1定義泛型方法

class Demo{
	public <T> T fun(T t){			// 可以接收任意類型的數據
		return t ;					// 直接把參數返回
	}
};
public class GenericsDemo26{
	public static void main(String args[]){
		Demo d = new Demo()	;	// 實例化Demo對象
		String str = d.fun("李興華") ; //	傳遞字符串
		int i = d.fun(30) ;		// 傳遞數字,自動裝箱
		System.out.println(str) ;	// 輸出內容
		System.out.println(i) ;		// 輸出內容
	}
};

2.2通過泛型方法返回泛型類的實例

class Info<T extends Number>{	// 指定上限,只能是數字類型
	private T var ;		// 此類型由外部決定
	public T getVar(){
		return this.var ;	
	}
	public void setVar(T var){
		this.var = var ;
	}
	public String toString(){		// 覆寫Object類中的toString()方法
		return this.var.toString() ;	
	}
};
public class GenericsDemo27{
	public static void main(String args[]){
		Info<Integer> i = fun(30) ;
		System.out.println(i.getVar()) ;
	}
	public static <T extends Number> Info<T> fun(T param){
		Info<T> temp = new Info<T>() ;		// 根據傳入的數據類型實例化Info
		temp.setVar(param) ;		// 將傳遞的內容設置到Info對象的var屬性之中
		return temp ;	// 返回實例化對象
	}
};

2.3使用泛型統一傳入參數的類型

class Info<T>{	// 指定上限,只能是數字類型
	private T var ;		// 此類型由外部決定
	public T getVar(){
		return this.var ;	
	}
	public void setVar(T var){
		this.var = var ;
	}
	public String toString(){		// 覆寫Object類中的toString()方法
		return this.var.toString() ;	
	}
};
public class GenericsDemo28{
	public static void main(String args[]){
		Info<String> i1 = new Info<String>() ;
		Info<String> i2 = new Info<String>() ;
		i1.setVar("HELLO") ;		// 設置內容
		i2.setVar("李興華") ;		// 設置內容
		add(i1,i2) ;
	}
	public static <T> void add(Info<T> i1,Info<T> i2){
		System.out.println(i1.getVar() + " " + i2.getVar()) ;
	}
};
如果add方法中兩個泛型的類型不統一,則編譯會出錯。
class Info<T>{	// 指定上限,只能是數字類型
	private T var ;		// 此類型由外部決定
	public T getVar(){
		return this.var ;	
	}
	public void setVar(T var){
		this.var = var ;
	}
	public String toString(){		// 覆寫Object類中的toString()方法
		return this.var.toString() ;	
	}
};
public class GenericsDemo29{
	public static void main(String args[]){
		Info<Integer> i1 = new Info<Integer>() ;
		Info<String> i2 = new Info<String>() ;
		i1.setVar(30) ;		// 設置內容
		i2.setVar("李興華") ;		// 設置內容
		add(i1,i2) ;
	}
	public static <T> void add(Info<T> i1,Info<T> i2){
		System.out.println(i1.getVar() + " " + i2.getVar()) ;
	}
};

3、泛型數組

public class GenericsDemo30{
	public static void main(String args[]){
		Integer i[] = fun1(1,2,3,4,5,6) ;	// 返回泛型數組
		fun2(i) ;
	}
	public static <T> T[] fun1(T...arg){	// 接收可變參數
		return arg ;			// 返回泛型數組
	}
	public static <T> void fun2(T param[]){	// 輸出
		System.out.print("接收泛型數組:") ;
		for(T t:param){
			System.out.print(t + "、") ;
		}
	}
};

4、泛型的嵌套設置

Demo類中的info屬性是Info類的這種屬性,Info類本身需要兩個泛型。
class Info<T,V>{		// 接收兩個泛型類型
	private T var ;
	private V value ;
	public Info(T var,V value){
		this.setVar(var) ;
		this.setValue(value) ;
	}
	public void setVar(T var){
		this.var = var ;
	}
	public void setValue(V value){
		this.value = value ;
	}
	public T getVar(){
		return this.var ;
	}
	public V getValue(){
		return this.value ;
	}
};
class Demo<S>{
	private S info ;
	public Demo(S info){
		this.setInfo(info) ;
	}
	public void setInfo(S info){
		this.info = info ;
	}
	public S getInfo(){
		return this.info ;
	}
};
public class GenericsDemo31{
	public static void main(String args[]){
		Demo<Info<String,Integer>> d = null ;		// 將Info作為Demo的泛型類型
		Info<String,Integer> i = null ;	// Info指定兩個泛型類型
		i = new Info<String,Integer>("李興華",30) ;	 // 實例化Info對象
		d = new Demo<Info<String,Integer>>(i) ;	// 在Demo類中設置Info類的對象
		System.out.println("內容一:" + d.getInfo().getVar()) ;
		System.out.println("內容二:" + d.getInfo().getValue()) ;
	}
};
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM