Fight With Me!!!

导航

泛型类型限定和通配符类型限定

泛型类型变量的限定

泛型的基础知识可以参考其他教程。

如果在方法前指定了<T>,那么就是说,方法的这个泛型类型和类定义时的泛型类型无关,这个特性让泛型方法可以定义在普通类中而不是泛型类中。

我们都知道,泛型中可以限定类型变量必须实现某几个接口或者继承某个类,多个限定类型用&分隔,类必须放在限定列表中所有接口的前面。例如:

 

[java] view plain copy
 
 print?在CODE上查看代码片派生到我的代码片
  1. import java.io.Serializable;  
  2.   
  3. /** 
  4.  * ICE 
  5.  * 2016/10/17 0017 14:12 
  6.  */  
  7. public class Demo {  
  8.     public static void main(String[] args) {  
  9.         D<A> d = new D<>();  
  10.         A a = new A();  
  11.         d.test1(a);  
  12.         B b = new B();  
  13.         d.test1(b);  
  14.         C c = new C();  
  15.         d.test1(c);  
  16.   
  17.         d.test2("test");  
  18.     }  
  19. }  
  20.   
  21. class A implements Serializable, Cloneable {  
  22.     @Override  
  23.     public String toString() {  
  24.         return "A{}";  
  25.     }  
  26. }  
  27.   
  28. class B extends A {  
  29.     @Override  
  30.     public String toString() {  
  31.         return "B{}";  
  32.     }  
  33. }  
  34.   
  35. class C extends A {  
  36.     @Override  
  37.     public String toString() {  
  38.         return "C{}";  
  39.     }  
  40. }  
  41.   
  42. class D<T extends A & Serializable & Cloneable> {  
  43.     public void test1(T t) {  
  44.         System.out.println(t);  
  45.     }  
  46.   
  47.     public <T> void test2(T t) {  
  48.         System.out.println(t);  
  49.     }  
  50. }  

 

输出:

 

[plain] view plain copy
 
 print?在CODE上查看代码片派生到我的代码片
  1. A{}  
  2. B{}  
  3. C{}  
  4. test  

 

 

通配符类型

通配符“?”同样可以对类型进行限定。可以分为子类型限定、超类型限定和无限定。通配符不是类型变量,因此不能在代码中使用"?"作为一种类型。

 

子类型限定

表示类型的上界,类似泛型的类型变量限定,格式是:? extends X。

特点:

1、限定为X和X的子类型,但不知道具体是哪个子类型,可能是怕导致类型转换错误(比如向下转型时编译不会报错,但是如果超类引用不是指向子类对象,那么运行时会报错),所以作为方法的参数时,这里禁止传递特定的类型。

2、作为方法的参数时,可以传递null。

作用:主要用来安全地访问数据,可以访问X及其子类型。

 

[java] view plain copy
 
 print?在CODE上查看代码片派生到我的代码片
  1. import java.util.ArrayList;  
  2. import java.util.List;  
  3.   
  4. /** 
  5.  * ICE 
  6.  * 2016/10/17 0017 14:12 
  7.  */  
  8. public class Demo {  
  9.     public static void main(String[] args) {  
  10.         A a = new A();  
  11.         B b = new B();  
  12.         C c = new C();  
  13.   
  14.         List<A> list = new ArrayList<>();  
  15.         list.add(a);  
  16.         list.add(b);  
  17.         list.add(c);  
  18.         //根据list的值,我们可以给列表中的对象做<? extends A>限定,因为都是A和A的子类,get返回值赋给A是完全合法的  
  19.         List<? extends A> list1 = list;  
  20.         list.add(null);  
  21.         for (int i = 0; i < list1.size(); i++) {  
  22.             A a1 = list1.get(i);  
  23.             System.out.println(a1);  
  24.         }  
  25.   
  26.         //这里如果set任何非null的值,编译器都会报错  
  27.         D<? extends A> d = new D<>();  
  28.         d.set(null);  
  29.     }  
  30. }  
  31.   
  32. class A {  
  33.     @Override  
  34.     public String toString() {  
  35.         return "A{}";  
  36.     }  
  37. }  
  38.   
  39. class B extends A {  
  40.     @Override  
  41.     public String toString() {  
  42.         return "B{}";  
  43.     }  
  44. }  
  45.   
  46. class C extends A {  
  47.     @Override  
  48.     public String toString() {  
  49.         return "C{}";  
  50.     }  
  51. }  
  52.   
  53. class D<T> {  
  54.   
  55.     public void test1(T t) {  
  56.         System.out.println(t);  
  57.     }  
  58.   
  59.     public void set(T t) {  
  60.   
  61.     }  
  62. }  

输出:

 

 

[plain] view plain copy
 
 print?在CODE上查看代码片派生到我的代码片
  1. A{}  
  2. B{}  
  3. C{}  
  4. null  

 

 

超类型限定

 

表示类型的下界,格式是:? super X。

特点:

1、限定为X和X的超类型,直至Object类,因为不知道具体是哪个超类型,因此方法返回的类型只能赋给Object。

2、因为可以向上转型,所以作为方法的参数时,可以传递X以及X的子类型。

3、作为方法的参数时,可以传递null。

作用:主要用来安全地写入数据,可以写入X及其子类型。

[java] view plain copy
 
 print?在CODE上查看代码片派生到我的代码片
  1. /** 
  2.  * ICE 
  3.  * 2016/10/17 0017 14:12 
  4.  */  
  5. public class Demo {  
  6.     public static void main(String[] args) {  
  7.         A a = new A();  
  8.         B b = new B();  
  9.         C c = new C();  
  10.   
  11.         D<? super A> d = new D<>();  
  12.         Object o = d.get();  
  13.   
  14.         d.set(a);  
  15.         d.set(b);  
  16.         d.set(c);  
  17.         d.set(null);  
  18.     }  
  19. }  
  20.   
  21. class A {  
  22.     @Override  
  23.     public String toString() {  
  24.         return "A{}";  
  25.     }  
  26. }  
  27.   
  28. class B extends A {  
  29.     @Override  
  30.     public String toString() {  
  31.         return "B{}";  
  32.     }  
  33. }  
  34.   
  35. class C extends A {  
  36.     @Override  
  37.     public String toString() {  
  38.         return "C{}";  
  39.     }  
  40. }  
  41.   
  42. class D<T> {  
  43.     public void set(T t) {  
  44.     }  
  45.   
  46.     public T get() {  
  47.         return null;  
  48.     }  
  49. }  

无限定

无限定不等于可以传任何值,相反,作为方法的参数时,只能传递null,作为方法的返回时,只能赋给Object。

 

[java] view plain copy
 
 print?在CODE上查看代码片派生到我的代码片
  1. /** 
  2.  * ICE 
  3.  * 2016/10/17 0017 14:12 
  4.  */  
  5. public class Demo {  
  6.     public static void main(String[] args) {  
  7.         D<?> d = new D<>();  
  8.         Object o = d.get();  
  9.         d.set(null);  
  10.     }  
  11. }  
  12.   
  13. class A {  
  14.     @Override  
  15.     public String toString() {  
  16.         return "A{}";  
  17.     }  
  18. }  
  19.   
  20. class B extends A {  
  21.     @Override  
  22.     public String toString() {  
  23.         return "B{}";  
  24.     }  
  25. }  
  26.   
  27. class C extends A {  
  28.     @Override  
  29.     public String toString() {  
  30.         return "C{}";  
  31.     }  
  32. }  
  33.   
  34. class D<T> {  
  35.     public void set(T t) {  
  36.     }  
  37.   
  38.     public T get() {  
  39.         return null;  
  40.     }  
  41. }  

有什么作用呢?对于一些简单的操作比如不需要实际类型的方法,就显得比泛型方法简洁。

 

 

[java] view plain copy
 
 print?在CODE上查看代码片派生到我的代码片
    1. /** 
    2.  * ICE 
    3.  * 2016/10/17 0017 14:12 
    4.  */  
    5. public class Demo {  
    6.     public static void test(D<?> d) {  
    7.         System.out.println(d == null);  
    8.     }  
    9.   
    10.     public static <T> void test1(D<T> d) {  
    11.         System.out.println(d == null);  
    12.     }  
    13.   
    14.     public static void main(String[] args) {  
    15.         D d = new D();  
    16.         Demo.test(d);  
    17.         Demo.test1(d);  
    18.     }  
    19. }  
    20.   
    21. class D<T> {  
    22. }  

posted on 2017-02-23 17:59  nickTimer  阅读(1770)  评论(0编辑  收藏  举报