Java学习者论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

手机号码,快捷登录

恭喜Java学习者论坛(https://www.javaxxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,购买链接:点击进入购买VIP会员
JAVA高级面试进阶视频教程Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程

Go语言视频零基础入门到精通

Java架构师3期(课件+源码)

Java开发全终端实战租房项目视频教程

SpringBoot2.X入门到高级使用教程

大数据培训第六期全套视频教程

深度学习(CNN RNN GAN)算法原理

Java亿级流量电商系统视频教程

互联网架构师视频教程

年薪50万Spark2.0从入门到精通

年薪50万!人工智能学习路线教程

年薪50万!大数据从入门到精通学习路线年薪50万!机器学习入门到精通视频教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程 MySQL入门到精通教程
查看: 315|回复: 0

[泛型学习]java范型有限制通配符的使用实例

[复制链接]
  • TA的每日心情
    开心
    2021-3-12 23:18
  • 签到天数: 2 天

    [LV.1]初来乍到

    发表于 2014-10-28 23:55:32 | 显示全部楼层 |阅读模式
    大概有限制通配符的使用是源于java的泛型的不可变性,所谓的不可变性就是说对于两个Set<T1>和Set<T2>,不管T1和T2谁是谁的父类,Set<T1>和Set<T2>都不会是父子类的关系。

    Java泛型的不可变性在应用中可能会遇到一些不方便的地方,尽管它很安全,比如一段这样的代码,加入我们要自己实现一个简单的List类如下:

    1. public class MyList< T> {   
    2.   
    3.     private T[] elements = null;   
    4.   
    5.     private int cursor = -1;   
    6.   
    7.     private static final int DEFAULT_CAPACITY = 10;   
    8.   
    9.     public MyList() {   
    10.         this(DEFAULT_CAPACITY);   
    11.     }   
    12.   
    13.     public MyList(int capacity) {   
    14.         @SuppressWarnings("unchecked")   
    15.         T[] t = (T[]) new Object[capacity];   
    16.         elements = t;   
    17.     }   
    18.   
    19.     private void allocateNew() {   
    20.         @SuppressWarnings("unchecked")   
    21.         T[] t = (T[]) new Object[elements.length * 2];   
    22.         for (int i = 0; i < elements.length; i++) {   
    23.             t[i] = elements[i];   
    24.         }   
    25.         elements = t;   
    26.     }   
    27.   
    28.     public MyList< T> add(T t) {   
    29.         if (cursor >= elements.length - 1) {   
    30.             allocateNew();   
    31.         }   
    32.   
    33.         cursor++;   
    34.         elements[cursor] = t;   
    35.         return this;   
    36.     }   
    37.   
    38.     public T get(int i) {   
    39.         return elements[i];   
    40.     }   
    41.   
    42.     public int size() {   
    43.         return elements.length;   
    44.     }   

    45.   

    46.     public MyList< T> addAll(MyList< T> myList) {   
    47.         int size = myList.size();   
    48.         for (int i = 0; i < size; i++) {   
    49.             add(myList.get(i));   
    50.         }   
    51.         return this;   
    52.     }   
    53. }  
    复制代码
    很简单,内部维护一个数组去实现列表,下面是使用这个类的代码:

    1. public class InvariantTester {   
    2.   
    3.     public static void main(String[] args) {   
    4.         MyList< CharSequence> charSeqList = new MyList< CharSequence>();   
    5.         charSeqList.add("s").add("t").add("r").add("i").add("n").add("g");   
    6.   
    7.         MyList< String> stringList = new MyList< String>();   
    8.         stringList.add("a").add("b").add("c").add("d").add("e").add("f");   
    9.   
    10.         charSeqList.addAll(stringList);   
    11.         for(int i=0;i< charSeqList.size();i++)
    12.             System.out.print(charSeqList.get(i)+"  ");
    13.         System.out.println();
    14.         
    15.     }   
    16.   
    17. }  
    复制代码
      这里前面的charSeqList.add("s").add("t").add("r").add("i").add("n").add("g")这步是不会报错的,而后边的charSeqList.addAll(stringList)是通不过编译的,原因就是泛型的不可变性,这里就要通过有限制的通配符类型去解决了,很简单,修改一下addAll的方法声明就可以了:

    1. public MyList< T> addAll(MyList< ? extends T> myList) {   
    2.      int size = myList.size();   
    3.      for (int i = 0; i < size; i++) {   
    4.         add(myList.get(i));   
    5.     }   
    6.     return this;   
    7.   }  
    复制代码
    这里就是有限制通配符类型的一个典型应用,当然还可以使用< ? super T>这种限制方式的。

       为了在泛型的方法参数上获得最大限度的灵活性,就需要有限制通配符类型的参与了,这里需要重点介绍的是使用有限制通配符类型时的PECS(producer-extends, Consumer-super)原则,也就是 < ? extends T>和< ? super T>的使用时机选择的原则。

    如果类型是一个生产者,那么就使用extends,如果是消费者,那么就用super。

       比如前面的例子,addAll(MyList< ? extends T> myList)这个方法的参数是为了给MyList类消费的,所以参数是生产者,下面再举个消费者的例子。还是上边的MyList类,我再添加一个方法进去:

    1. public void copyTo(MyList< ? super T> dstList) {   
    2.         dstList.addAll(this);   
    3.    }  
    复制代码
      基本就是addAll()方法的逆方法,这里的参数dstList就是一个消费者了,同样,稍稍修改一下InvariantTester,加入这个方法的使用:

    1. public class InvariantTester {   
    2.   
    3.     public static void main(String[] args) {   
    4.         MyList< CharSequence> charSeqList = new MyList< CharSequence>();   
    5.         charSeqList.add("s").add("t").add("r").add("i").add("n").add("g");   
    6.   
    7.         MyList< String> stringList = new MyList< String>();   
    8.         stringList.add("a").add("b").add("c").add("d").add("e").add("f");   
    9.   
    10.         charSeqList.addAll(stringList);   
    11.         for(int i=0;i< charSeqList.size();i++)
    12.             System.out.print(charSeqList.get(i)+"  ");
    13.         System.out.println();
    14.         stringList.copyTo(charSeqList);
    15.         for(int i=0;i< charSeqList.size();i++)
    16.           System.out.print(charSeqList.get(i)+"  ");
    17.     }   
    18.   
    19. }  
    复制代码

       
         
         
          
          

            
          

            
          
         
       

      


    源码下载:http://file.javaxxz.com/2014/10/28/235531828.zip
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|Java学习者论坛 ( 声明:本站资料整理自互联网,用于Java学习者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2025-2-26 04:08 , Processed in 0.351206 second(s), 34 queries .

    Powered by Discuz! X3.4

    © 2001-2017 Comsenz Inc.

    快速回复 返回顶部 返回列表