ArrayList源码详尽解读(一)

最近相对有一些空余的时间,重新看了一下JDK1.8 ArraryList的源码,写了这篇比较详细的分析,这里主要是对1.8源码做分析,与1.6 1.7 ArraryList源码不同的地方,准备单独写在后面进行比较,当然,有的地方可能还是会提到一下。

内容比较多,分成几个部分慢慢写吧。

从这个类的作者开始讲起吧。



ArrayList作者

Josh Block这个响当当的名字相信不少程序猿都知道,就算不知道,似乎也有种似曾相识的感觉。没错,《Effective Java》这本书正是出自Josh Block之手。关于这本书,一些牛逼的程序员说,哎呀,这本书早就过时了,我都懒得看,要是这样,我也没话说。这本书的中文翻译有的地方似乎不怎么好,个人建议能够读一读英文版的,有好处。我是觉得这本书写的非常不错的,有的地方也是实实在在用到了,当然,建议有一定开发经验之后再去读,效果更佳。

Neal Gafter,《Java Puzzlers》作者,这本书也是牛逼了,这本书里面...抱歉,没有看过。反正牛逼就对了,现在似乎在微软,看了他的homepage,似乎在搞 C# 和 VB.net,你们看,大佬们并不受语言约束,管你什么语言,撸起袖子就是干。

下面正儿八经的来看看代码实现吧


ArrayList继承类和实现的接口

ArrayList继承了AbstractList,这是一个抽象类,里面包含了一些实现好的通用方法和一些没有实现的抽象方法,这里希望大家去看一下整个java Collection的架构设计。再基础一点,看下接口,抽象类相关的知识,有时间我会写。

ArrayList实现了四个接口,RandomAccess, Cloneable, java.io.Serializable这三个接口,这三个接口进去看一下,会发现这是三个空实现的接口,其实这三个接口的作用只是一个标记的作用。

实现了RandomAccess接口,表示用于标明实现该接口的List支持快速随机访问,主要目的是使算法能够在随机和顺序访问的list中表现的更加高效。看下面的一段代码,这里就根据是否实现了RandomAccess做了一个判断,不用我多说了吧。


Collections下的binarySearch方法

实现了Cloneable接口,表示可以进行浅克隆,浅克隆是指只负责克隆不可变类型的数据(比如基本数据类型、String类型),而不复制它所引用的对象,换言之,所有的对其他对象的引用都仍然指向原来的对象。具体做法是实现Cloneable接口,覆盖Object的clone()方法。这里关于这个接口,我查了一些资料,发现Josh Bloch本人也在一次Conversation里说过,由于早期时间不够的诸多原因,这是一个非常糟糕的设计,非常鸡肋,具体的内容参见http://www.artima.com/intv/bloch13.html(纯英文需翻墙),具体的设计糟糕在哪里这里不单独说明,并不影响我们阅读源码。

java.io.Serializable这个接口不想多说了,表示可以进行序列化功能,至于序列化是个什么东西,留给大家自行百度或者谷歌。

List<E> 是个泛型接口,里面定义了List列表的一些基本操作,非常好理解了。

下面看一下定义的一些字段。


ArrayList字段

第一个静态字段,serialVersionUID,这是序列化id,我就不多说了。

第二个静态字段,DEFAULT_CAPACITY,int类型,默认的容量,这里的容量和列表的大小是有区别的,容量表示能够存储多少内容,而列表的大小,也就是size 表示已经存储了多少数据。我们在初始化一个新的ArrayList的时候,可以指定容量,也可以不指定,使用默认的容量,如下图所示:



list使用默认容量和指定容量

第三个静态字段EMPTY_ELEMENTDATA,数组类型,表示空的数组,我们在初始化一个空的列表的时候,指向的都是这个空的数组,注意个空的数组是我们使用指定容量的构造方法时指向的,见上图中的第二个声明。

第四个静态字段DEFAULTCAPACITY_EMPTY_ELEMENTDATA,数组类型,默认的空的数组,这个就是当我们使用上图第一个构造方法时,指向的空数组。

第五个静态字段elementData,数组类型,这里就是ArrayList存储数据的地方,前面有一个transient的修饰符号,这个表示在序列化的时候,是不会序列化这个数组的,序列化这个东西还是简单说一下吧,我们程序运行的时候,所有的变量是存储在内存当中的,程序停止了,我们这些变量就被清空了,想要保存这些内存中的变量,我们就要从内存保存到磁盘中,这个时候的过程就叫做序列化,序列化后的内容就可以写进文件或者数据库,或者通过网络传输的方式传输到其他机器上去。那么为什么这个elementData字段在序列化的时候不需要序列化呢?其实也不是没有序列化,只是用了其他的方式对这个字段进行了序列化,因为我们知道,这个数组不一定都是存储满的,因为我们在初始化的时候会指定容量,或者使用默认的容量,存不满就会有很多空值,序列化这些空值是没有意义的,所以ArrayList提供了一个方法对这个字段进行序列化,见下图:


序列化elementData的方法

第六个字段,size,没什么好解释的。

其实类中间还定义了两个字段如图:


记录修改的次数

最大长度

第一个字段是记录对列表的修改次数,这个字段作用其实是为了保证一个线程的安全,具体不过多阐述,后面会写线程安全,第二个字段是约定的列表最大的长度,为int类型能够表示的最大值减去8,这个值是很大的,是2147483647-8,一般我们列表存储不到这么大的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值