• 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()) ;
    	}
    };
     
  • 相关阅读:
    Java Thread 源码
    新的篇章,新的开始,寄没有的希望于未来。
    命名的常用关键字
    通俗易懂的TCP三次握手
    Java多态
    servlet容器工作顺序
    IOC思想
    Spring MVC工作流程
    一对一,一对多,多对多
    JDBC的步骤
  • 原文地址:https://www.cnblogs.com/icenter/p/5277873.html
Copyright © 2020-2023  润新知