ArrayList序列化
ArrayList源代码中的
private transient E[] elementData;
声明为transient,为什么还可以序列化成功呢?
ArrayList重写了
private void writeObject(java.io.ObjectOutputStream s)
throws java.io.IOException{
int expectedModCount = modCount;
// Write out element count, and any hidden stuff
s.defaultWriteObject(); // Write out array length
s.writeInt(elementData.length); // Write out all elements in the proper order.
for (int i=0; i<size; i++)
s.writeObject(elementData[i]); if (modCount != expectedModCount) {
throw new ConcurrentModificationException();
}
}
在使用ObjectOutputStream序列化对象时会调用这个writeObject方法。
第二个问题是为什么要声明为transient呢?
在google了下,发现主流说法如下:
ArrayList实现了java.io.Serializable接口,所以ArrayList对象可以序列化到持久存储介质中。ArrayList的主要属性定义如下: * private static final long serialVersionUID = 8683452581122892189L;
* private transient Object elementData[];
* private int size; 可以看出serialVersionUID和size都将自动序列化到介质中,但elementData数组对象却定义为transient了。
也就是说 ArrayList中的所有这些元素都不会自动系列化到介质中。为什么要这样实现?因为elementData数组中存储的
“元素”其实仅是对这些元素的一个引用,并不是真正的对象,序列化一个对象的引用是毫无意义的,因为序列化是为了
反序列化,当你反序列化时,这些对象的引用已经不可能指向原来的对象了。所以在这儿需要手工的对ArrayList的元素进
行序列化操作。这就是writeObject()的作用。
果真如此么??????
验证下:
把ArrayList的内容完全copy到一个新类里面,命名为MyArrayList,如下:
public class MyArrayList<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable
{
private static final long serialVersionUID = 8683452581122892189L; /**
* The array buffer into which the elements of the ArrayList are stored.
* The capacity of the ArrayList is the length of this array buffer.
*/
private E[] elementData; 。。。。。。。。 private void writeObject(java.io.ObjectOutputStream s)
throws java.io.IOException{
int expectedModCount = modCount;
// Write out element count, and any hidden stuff
s.defaultWriteObject(); if (modCount != expectedModCount) {
throw new ConcurrentModificationException();
}
} /**
* Reconstitute the <tt>ArrayList</tt> instance from a stream (that is,
* deserialize it).
*/
private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException {
// Read in size, and any hidden stuff
s.defaultReadObject();
} }
把transient去掉,write/readObject采用默认方式。
测试下MyArraylist序列化功能:
MyArrayList al = new MyArrayList<String>();
al.add("sssssssssssssssss");
al.add("bbbbbbbbbbbbbbbbbbt");
al.add("gggggggggggggggggg"); ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("D:\\al.tmp"));
oos.writeObject(al); ObjectInputStream ois = new ObjectInputStream(new FileInputStream("D:\\al.tmp")); MyArrayList<String> a = (MyArrayList<String>)ois.readObject();
for(String s: a)
{
System.out.println(s);
}
输出结果为:
sssssssssssssssss
bbbbbbbbbbbbbbbbbbt
gggggggggggggggggg
到此证明:引用序列化无效的说法是错误的,这点在ObjectOutputStream中也有说明。
那是为什么呢?
既然是数组,要序列化到文件中,那就单独测试下数组对象的序列化和反序列化吧
String[] stra = new String[4];
stra[0] = "mmmmmmmmmm";
stra[2] = "nnnnnnnnnn"; oos = new ObjectOutputStream(new FileOutputStream("D:\\sa.tmp"));
oos.writeObject(stra); ois = new ObjectInputStream(new FileInputStream("D:\\sa.tmp")); String[] str = (String[])ois.readObject();
for(String s: str)
{
System.out.println(s);
}
输出结果为:
mmmmmmmmmm
null
nnnnnnnnnn
null
从输出结果来看,数组序列化时,不管是否有值,都会将整个数组序列化到文件中。
由此可以看出,比较靠谱的原因是:
ArrayList是会开辟多余空间来保存数据的,而系列化和反序列化这些没有存放数据的空间是要消耗更多资源的,所以ArrayList的数组就声明为transient,自己实现write/readObject方法,仅仅系列化已经存放的数据。
http://kakaluyi.iteye.com/blog/870137#
ArrayList序列化的更多相关文章
- 专题二、ArrayList序列化技术细节详解
一.绪论 所谓的JAVA序列化与反序列化,序列化就是将JAVA 对象以一种的形式保持,比如存放到硬盘,或是用于传输.反序列化是序列化的一个逆过程. JAVA规定被序列化的对象必须实现java.io.S ...
- Java中ArrayList源码分析
一.简介 ArrayList是一个数组队列,相当于动态数组.每个ArrayList实例都有自己的容量,该容量至少和所存储数据的个数一样大小,在每次添加数据时,它会使用ensureCapacity()保 ...
- 深入分析Java的序列化与反序列化
序列化是一种对象持久化的手段.普遍应用在网络传输.RMI等场景中.本文通过分析ArrayList的序列化来介绍Java序列化的相关内容.主要涉及到以下几个问题: 怎么实现Java的序列化 为什么实现了 ...
- Java基础之数组序列化、反序列化 小发现(不知道 是不是有问题)
结论: 数组,无论是否声明为transient,都是可以序列化.反序列化的. 测试情况如下: 1.两种类型的数组:int .String: 2 声明为transient 或者不做任何修饰:. 3. ...
- Java 序列化 对象序列化和反序列化
Java 序列化 对象序列化和反序列化 @author ixenos 对象序列化是什么 1.对象序列化就是把一个对象的状态转化成一个字节流. 我们可以把这样的字节流存储为一个文件,作为对这个对象的复制 ...
- java基础( 九)-----深入分析Java的序列化与反序列化
序列化是一种对象持久化的手段.普遍应用在网络传输.RMI等场景中.本文通过分析ArrayList的序列化来介绍Java序列化的相关内容.主要涉及到以下几个问题: 怎么实现Java的序列化 为什么实现了 ...
- Java基础18:Java序列化与反序列化
更多内容请关注微信公众号[Java技术江湖] 这是一位阿里 Java 工程师的技术小站,作者黄小斜,专注 Java 相关技术:SSM.SpringBoot.MySQL.分布式.中间件.集群.Linux ...
- Java对象序列化全面总结
前言 Java允许我们在内存中创建可复用的Java对象,但一般情况下,这些对象的生命周期不会比JVM的生命周期更长.但在现实应用中,可能要求在JVM停止运行之后能够保存(持久化)指定的对象,并在将来重 ...
- Java基础(十一)--Serializable和Externalizable接口实现序列化
序列化在日常开发中经常用到,特别是涉及到网络传输的时候,例如调用第三方接口,通过一个约定好的实体进行传输,这时你必须实现序列 化,这些都是大家都了解的内容,所以文章也会讲一下序列化的高级内容. 序列化 ...
随机推荐
- sencha touch 在线实战培训 第一期 第四节
2014.1.4晚上8点开的课 第一节收费课程,还是有几位同学付费了,这些课程也录像了的,以后也会持续销售. 本期培训一共八节,前三堂免费,后面的课程需要付费才可以观看. 本节内容: ...
- mysqlslap 压测工具使用说明
PS:今天一同事问我有木有比较靠谱的mysql压力测试工具可用.其实mysql自带就有一个叫mysqlslap的压力测试工具,还是模拟的不错的.下面举例说说.mysqlslap是从5.1.4版开始的一 ...
- Laya 图集动画
参考: 图集动画运用 一.准备素材 从爱给网找到几个素材 二.使用Laya的图集工具 菜单栏选择工具->图集打包工具,然后选择序列图所在的文件夹 生成了个.rec...说好的.atlas呢... ...
- 23种设计模式之中介者模式(Mediator)
中介者模式是一种对象的行为型模式,通过一个中介对象来封装一系列的对象交互.中介者使得各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互.中介者对象的存在保证了对象结构上的稳 ...
- Jquery操作select选项集合,判断集合中是否存在option
转载:http://www.cnblogs.com/pepcod/archive/2012/07/03/JavaScript.html Query获取Select选择的Text和Value: 语法解释 ...
- 【CF888G】Xor-MST Trie树(模拟最小生成树)
[CF888G]Xor-MST 题意:给你一张n个点的完全图,每个点有一个权值ai,i到j的边权使ai^aj,求这张图的最小生成树. n<=200000,ai<2^30 题解:学到了求最小 ...
- iOS 禁止手势滑动翻页
- (void)viewDidAppear:(BOOL)animated{ [super viewDidAppear:animated]; // 禁用 iOS7 返回手势 if ([self.navi ...
- jenkins遇到含中文路径的SVN地址时认证通不过
安装插件:http://mirror.xmission.com/jenkins/plugins/subversion/2.5/subversion.hpi 可以解决svn中文目录问题 百度云:http ...
- vue--双向数据绑定
<template> <div id="app"> <p>{{msg}}</p> <input v-model="m ...
- 8.26 js
2018-8-26 20:35:53 这两天周末,一直在看苏东坡传! 明天正常学python 用心学!