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入门到精通教程
查看: 353|回复: 0

[泛型学习]Jdk1.5中的泛型 (详细版)

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

    [LV.1]初来乍到

    发表于 2014-10-30 23:56:42 | 显示全部楼层 |阅读模式
    本来只转载了个链接,和一个简单的使用程序,但昨天不小心看到有人批判jdk1.5,先说java要强制转型不好的问题没解决,
    容器不能放基类型不好,接着说泛型没用。而恰恰Jdk1.5中解决了这些问题,所以感叹之余,把这篇文章改一下,详细的说说泛型。 一,Java中的泛型:

         在Java中能使用到泛型的多是容器类,如各种list map set,因为Java是单根继承,所以容器里边可以放的内容是任何Object,所以从意义上讲原本的设计才是泛型。但用过Java的人是否感觉每次转型很麻烦呢? 而且会有些错误,比如一个容器内放入了异质对象,强制转型的时候会出现cast异常。而这中错误在编译器是
    无从发现的。

          所以jdk1.5中提供了泛型,这个泛型其实是向c++靠拢了.好,我们先看几个实例再细说原理。
      
       
       
         
       

         
       
      
    二,泛型的用法:(多个实例)
      

    1

    实例A

    2
    ArrayList
    <
    String
    >
      strList  
    =
       
    new
      ArrayList
    <
    String
    >
    ();

    3
    strList.add(
    "
    1
    "
    );

    4
    strList.add(
    "
    2
    "
    );

    5
    strList.add(
    "
    3
    "
    );

    6

    //
    关键点(1) 注意下边这行,没有强制转型


    7

    String str  
    =
      strList.get(
    1
    );

    8

    //
    关键点(2)然後我们加入,这个时候你会发现编译器报错,错误在编译器被发现,错误当然是发现的越早越好


    9

    strList.add(
    new
      Object());



    1

    实例B

    2
    ArrayList
    <
    Integer
    >
      iList  
    =
       
    new
      ArrayList
    <
    Integer
    >
    ();

    3

    //
    关键点(3) 注意直接把整数放入了集合中,而没有用Integer包裹


    4

    iList.add(
    1
    );

    5
    iList.add(
    2
    );

    6
    iList.add(
    3
    );

    7

    //
    关键点(4)同样直接取出就是int


    8

    int
      num  
    =
      iList.get(
    1
    );



    1

    实例C

    2

    //
    关键点(5)展示一下key-value的时候要怎么写,同时key和value也可以是基本类型了。


    3

    HashMap
    <
    Integer,Integer
    >
      map  
    =
       
    new
      HashMap
    <
    Integer,Integer
    >
    ();

    4
    map.put(
    1
    ,  
    11
    );

    5
    map.put(
    2
    ,  
    22
    );

    6
    map.put(
    3
    ,  
    33
    );

    7

    int
      inum  
    =
      map.get(
    1
    );

    8


    三,看完了实例了,详细来说说为什么吧
    首先jdk1.5中的泛型,第一个解决的问题,就是Java中很多不必要的强制转型了,具体的实现,我们以ArrayList
    为例,下边是ArrayList中的片断代码:



      1

    ArrayList类的定义,这里加入了
    <
    E
    >


      2

    public
      
    class
      ArrayList
    <
    E
    >
      
    extends
      AbstractList
    <
    E
    >


      3
            
    implements
      List
    <
    E
    >
    , RandomAccess, Cloneable, java.io.Serializable

      4


      5

    //
    get方法,返回不再是Object 而是E


      6

    public
      E get(
    int
      index)

    {
      7    RangeCheck(index);
      8    return elementData[index];
      9}


    10

    //
    add方法,参数不再是Object 而是E


    11

    public
      
    boolean
      add(E o)

    {
    12    ensureCapacity(size + 1);  // Increments modCount!!
    13    elementData[size++] = o;
    14    return true;
    15}


    16


    四,Boxing 和UnBoxing
    看到上边的关键点(3)和(4)是否感觉惊奇呢,因为Java中烦人的除了强制转型,另一个就是基础类型了
    放入容器的时候要包装,取出了还要转回。Jdk1.5中解决了这个问题.如上边的使用方法

    五,泛型的生命周期(使用注意事项)
    如果我们试着把ArrayList<String> list的内容序列化,然後再读取出来,在使用的过程中会发现出错,
    为什么呢?用Stream读取一下回来的数据,你会发现<String>不见了,list变成了普通的ArrayList,而不是
    参数化型别的ArrayList了,为什么会这样呢 ?见下边的比较 六,C++的泛型和Java的泛型
    在泛型的实现上,C++和Java有着很大的不同,
    Java是擦拭法实现的
    C++是膨胀法实现的
    因为Java原本实现就是泛型的,现在加入型别,其实是"窄化",所以采用擦拭法,在实现上,其实是封装了原本的
    ArrayList,这样的话,对于下边这些情况,Java的实现类只有一个。

      

    1

    ArrayList
    <
    Integer
    >
       .;   
    public
      
    class
      ArrayList

    2
    ArrayList
    <
    String
    >
       ..;   
    --
    同上
    --


    3
    ArrayList
    <
    Double
    >
       ..;   
    --
    同上
    --


    4
    而C
    ++
    采用的是膨胀法,对于上边的三种情况实际是每一种型别都对应一个实现,实现类有多个

    5
    list
    <
    int
    >
      li;               
    class
      list;
    //
    int 版本


    6

    list
    <
    string
    >
      ls;            
    class
      list;
    //
    string 版本


    7

    list
    <
    double
    >
      ld;            
    class
      list;
    //
    double 版本   
    这就造成了,在序列化后,Java不能分清楚原来的ArrayList是
    ArrayList<Integer>还是ArrayList

    七,题外话,在很多东西的实现上C++和Java有很多不同
    例如运算符的问题i=i++问题,详细看这里
    例如在C++中能很好实现的double-checked locking单态模式,在Java中几乎很难实现 详细看这里
    还有就是上边提到的泛型实现上。
      八,Jdk 1.5加入了不少新东西,有些能很大的提高开发质量,例如Jdk1.4 ,Jdk.15中StringBuffer的不同
    因为从1。4转入1。5不久,所以慢慢会发一些在1。5的使用过程中发现的东西。

    最后,我们还可以自己写类似ArrayList这样的泛型类,至于如何自定义泛型类,泛型方法请参见候捷先生的文章


      
      
       
       

         
       

         
       
      
    复制代码
    回复

    使用道具 举报

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

    本版积分规则

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

    GMT+8, 2025-2-25 21:57 , Processed in 0.386580 second(s), 46 queries .

    Powered by Discuz! X3.4

    © 2001-2017 Comsenz Inc.

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