发布日期:2013-03-07 11:40 来源:未知 标签: Java 泛型
 

一,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中的片断代码:

 1ArrayList类的定义,这里加入了<E>
 2public class ArrayList<E> extends AbstractList<E>
 3        implements List<E>, RandomAccess, Cloneable, java.io.Serializable
 4
 5//get方法,返回不再是Object 而是E
 6public E get(int index) {
 7    RangeCheck(index);
 8    return elementData[index];
 9}
10//add方法,参数不再是Object 而是E
11public 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的实现类只有一个。


1ArrayList<Integer>  .;   public class ArrayList
2ArrayList<String>  ..;   --同上--
3ArrayList<Double>  ..;   --同上--
4而C++采用的是膨胀法,对于上边的三种情况实际是每一种型别都对应一个实现,实现类有多个
5list<int> li;                class list; //int 版本
6list<string> ls;             class list; //string 版本
7list<double> ld;             class list; //double 版本   
这就造成了,在序列化后,Java不能分清楚原来的ArrayList是
ArrayList<Integer>还是ArrayList


 

相关评论

专题信息
    本教程的主要讲解java语言的核心基础知识,使读者能有个良好的语言基础,为以后进一步提高打下基础。宗旨是帮助更多想学习java的朋友快速入门,如果你是一个Java语言的初学者,那么就从Java教程,java数组,java环境变量配置,java网络编程,技巧等这里开始学习Java吧!