java中的泛型

来源:互联网 发布:淘宝人群标签在哪里看 编辑:程序博客网 时间:2024/06/05 17:02

之前对泛型的理解一直停留在listj集合中的元素限定的那块,后来慢慢的接触到了接口的泛型,类以及方法的泛型。下面结合查到的资料,算是记录一下。

由于集合中的泛型限定太多简单就不举例了,现在来说说接口,类,和方法中的泛型。我们常见的比如 T,E,V,K等形式的参数常用于表示泛型形参,接收来自外部使用时候传入的类型实参

我们看一个最简单的泛型类和方法定义:

 1 public class GenericTest { 2  3     public static void main(String[] args) { 4  5         Box<String> name = new Box<String>("corn"); 6         System.out.println("name:" + name.getData()); 7     } 8  9 }10 11 class Box<T> {12 13     private T data;14 15     public Box() {16 17     }18 19     public Box(T data) {20         this.data = data;21     }22 23     public T getData() {24         return data;25     }26 27 } 

对于不同传入的类型实参,生成的相应对象实例的类型是一样的。如:

 1 public class GenericTest { 2  3     public static void main(String[] args) { 4  5         Box<String> name = new Box<String>("corn"); 6         Box<Integer> age = new Box<Integer>(712); 7  8         System.out.println("name class:" + name.getClass());      // com.qqyumidi.Box 9         System.out.println("age class:" + age.getClass());        // com.qqyumidi.Box10         System.out.println(name.getClass() == age.getClass());    // true11 12     }13 14 }
下面说说通配符的问题;

接着上面的结论,我们知道,Box<Number>和Box<Integer>实际上都是Box类型,现在需要继续探讨一个问题,那么在逻辑上,类似于Box<Number>和Box<Integer>是否可以看成具有父子关系的泛型类型呢?

为了弄清这个问题,我们继续看下下面这个例子:

复制代码
 1 public class GenericTest { 2  3     public static void main(String[] args) { 4  5         Box<Number> name = new Box<Number>(99); 6         Box<Integer> age = new Box<Integer>(712); 7  8         getData(name); 9         10         //The method getData(Box<Number>) in the type GenericTest is 11         //not applicable for the arguments (Box<Integer>)12         getData(age);   //编译错误13 14     }15     16     public static void getData(Box<Number> data){17         System.out.println("data :" + data.getData());18     }19 20 }
显然,通过提示信息,我们知道Box<Number>在逻辑上不能视为Box<Integer>的父类。我们需要一个在逻辑上可以用来表示同时是Box<Integer>和Box<Number>的父类的一个引用类型,由此,类型通配符应运而生。

通配符一般使用?代替具体的类型实参,注意,此处是实参。而不是类型形参且Box<?>在逻辑上是Box<Integer>、Box<Number>...等所有Box<具体类型实参>的父类。由此,我们依然可以定义泛型方法,来完成此类需求。

 1 public class GenericTest { 2  3     public static void main(String[] args) { 4  5         Box<String> name = new Box<String>("corn"); 6         Box<Integer> age = new Box<Integer>(712); 7         Box<Number> number = new Box<Number>(314); 8  9         getData(name);10         getData(age);11         getData(number);12     }13 14     public static void getData(Box<?> data) {15         System.out.println("data :" + data.getData());16     }17 18 }

有时候,我们还可能听到类型通配符上限和类型通配符下限。具体有是怎么样的呢?

在上面的例子中,如果需要定义一个功能类似于getData()的方法,但对类型实参又有进一步的限制:只能是Number类及其子类。此时,需要用到类型通配符上限。

复制代码
 1 public class GenericTest { 2  3     public static void main(String[] args) { 4  5         Box<String> name = new Box<String>("corn"); 6         Box<Integer> age = new Box<Integer>(712); 7         Box<Number> number = new Box<Number>(314); 8  9         getData(name);10         getData(age);11         getData(number);12         13         //getUpperNumberData(name); // 114         getUpperNumberData(age);    // 215         getUpperNumberData(number); // 316     }17 18     public static void getData(Box<?> data) {19         System.out.println("data :" + data.getData());20     }21     22     public static void getUpperNumberData(Box<? extends Number> data){23         System.out.println("data :" + data.getData());24     }25 26 }

此时,显然,在代码//1处调用将出现错误提示,而//2 //3处调用正常。 因为之前getData(Box<?> data); 没有进一步进行通配符的限制。

类型通配符上限通过形如Box<? extends Number>形式定义,相对应的,类型通配符下限为Box<? super Number>形式,其含义与类型通配符上限正好相反,在此不作过多阐述了。



原创粉丝点击