码迷,mamicode.com
首页 > 编程语言 > 详细

Java中的泛型方法

时间:2016-03-15 06:18:52      阅读:288      评论:0      收藏:0      [点我收藏+]

标签:

?????? 泛型是什么意思在这就不多说了,而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?<?2)?return?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("",?1,?1.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()) ;
	}
};
?

Java中的泛型方法

标签:

原文地址:http://www.cnblogs.com/icenter/p/5277873.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!