private transient E[] elementData;
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方法,仅仅系列化已经存放的数据。
分享到:
相关推荐
98<br><br>0153 如何自定义数字小数点左边分组位数 98<br><br>0154 格式化输入数据为货币格式 99<br><br>0155 如何计算两个整数的乘积 99<br><br>0156 如何将二进制数转换为十进制数 100<br><br>0157 如何...
ArrayList<Shop> list = (ArrayList<Shop>)session.getAttribute(ISysConstans.CARNAME); if(list!=null){ for(int i=0;i<list.size();i++){ Shop s = list.get(i); float sum = s....
DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><br><html><br> <head><br> </head><br> <body><br> <table><br> <tr><br> <td><%@ include file="../menu.txt"%><br> </td><br> </tr>...
<summary>拼接DataGridView,返回ArrayList 数组</summary> <param name="dgv" /> <returns /> <remarks /> </member> - <member name="M:Pic_Chart_Load.UpLoad_data_Insert.Return_Arr_OneS_data_by_...
<br> }<br>}<br><br>答案::填空第1题<br>x=10,a=3,b=4,c=5<br>填空第2题<br>java.util<br>填空第3题<br>(public )(static )(void)(main)(String args[])<br>填空第4题<br>1<br>填空第5题<br>
第一部分 使用ASP.NET Web表单<br><br>第1章 建立ASP.NET页面 <br><br>1.1 ASP.NET和.NET框架 <br>1.1.1 .NET框架类库 <br>1.1.2 理解名称空间 <br>1.1.3 标准的ASP.NET名称空间 <br>1.1.4 与.NET框架兼容的语言 <br...
第一部分 使用ASP.NET Web表单<br><br>第1章 建立ASP.NET页面 <br><br>1.1 ASP.NET和.NET框架 <br>1.1.1 .NET框架类库 <br>1.1.2 理解名称空间 <br>1.1.3 标准的ASP.NET名称空间 <br>1.1.4 与.NET框架兼容的语言 <br...
第一部分 使用ASP.NET Web表单<br><br>第1章 建立ASP.NET页面 <br><br>1.1 ASP.NET和.NET框架 <br>1.1.1 .NET框架类库 <br>1.1.2 理解名称空间 <br>1.1.3 标准的ASP.NET名称空间 <br>1.1.4 与.NET框架兼容的语言 <br...
第一部分 使用ASP.NET Web表单<br><br>第1章 建立ASP.NET页面 <br><br>1.1 ASP.NET和.NET框架 <br>1.1.1 .NET框架类库 <br>1.1.2 理解名称空间 <br>1.1.3 标准的ASP.NET名称空间 <br>1.1.4 与.NET框架兼容的语言 <br...
第一部分 使用ASP.NET Web表单<br><br>第1章 建立ASP.NET页面 <br><br>1.1 ASP.NET和.NET框架 <br>1.1.1 .NET框架类库 <br>1.1.2 理解名称空间 <br>1.1.3 标准的ASP.NET名称空间 <br>1.1.4 与.NET框架兼容的语言 <br...
<%@ page import="java.util.ArrayList" %> <%@ page import="com.yxq.valuebean.ArticleTypeBean" %> <% ArrayList typelist=(ArrayList)session.getAttribute("artTypeList"); %> <html> <head> <title>博客后台-...
ArrayList<Goods> goods = db.Search(goodsname); int count = 0; Goods goods1 = null; for (; count < goods.size(); count++) { goods1 = goods.get(count); out.println("<tr>"); out....
一个C++(Ubuntu16.04+QT5.9.1)通过JNI,调用JAVA类及方法的示例。通过JNI传递和返回多种类型的参数,boolean ,int,String,ArrayList<string>,ArrayList嵌套ArrayList<ArrayList<String>>等。
这里的 <T> 表示泛型,T 表示泛型中装载的类型为T类型,等到需要的时候,我们可以具体这个 T。我们在使用动态数组实现 ArrayList 的时候,如果希望这个 ArrayList 不仅仅支持一个类型的话,我们可以给这个 ArrayList...
ArrayList<Users> list; UserService service; Users user; Pager page=new Pager(); public Pager getPage() { return page; } public void setPage(Pager page) { this.page = page; } public ...
<br>第1章 Java基础 <br>1.1 转换基本数据类型 <br>1.2 Java的运算符 <br>1.3 控制程序的流程 <br>1.4 计算阶乘 <br>1.5 实现命令行程序 <br>第2章 Java面向对象程序设计 <br>2. 1 复数类 <br>2. 2 equals.chashCode...
intent 传递 ArrayList<T>
Arraylist 和 List<T> 在使用的效率是不一样的,选择不同的集合 能使项目的性能有很大的提高!
<br/>2.3 在控件上进行格式化 <br/>2.3.1 基本Web控件属性 <br/>2.3.2 在Web控件上应用样式 <br/>2.4 小结 <br/><br/>第3章 用检验控件执行表单的检验 <br/><br/>3.1 使用客户端检验 <br/>3.1.1 配置客户端检验 <br/...
List<PageBean> list = new ArrayList<PageBean>(); newgetResouce newgetresouce = new newgetResouce(); //通过显示页面传递一个pagetype对象和PaginationBean对象 Page page = new Page(request....