1: 先阅读这边文章:http://www.importnew.com/21517.html

2:被transient修饰真的会被序列化吗?

反例:java.util.ArrayList中底层存储数组就是transient,但是实际上还是可以被成功序列化。具体原因如下:

   transient Object[] elementData;

  

我的测试代码:

class ArrayListDemo implements Serializable {
public static void main(String[] args) throws Exception {
ArrayList<Integer> data = new ArrayList<>();
data.add(1);
data.add(1);
data.add(1);
data.add(1); ByteArrayOutputStream bo = new ByteArrayOutputStream(); ObjectOutputStream out = new ObjectOutputStream(bo);
out.writeObject(data);
byte[] dataData = bo.toByteArray(); FileOutputStream fo = new FileOutputStream("data.dat");
fo.write(dataData);
fo.close(); FileInputStream fi = new FileInputStream("data.dat");
ObjectInputStream in = new ObjectInputStream(fi);
ArrayList<Integer> newList = (ArrayList<Integer>) in.readObject();
System.out.println(newList.size()); for (int i = 0; i < newList.size(); i++) { System.out.println(newList.get(i)); }
}
}  

输出:

数据还是成功序列化了,为什么会被序列化呢?分析原因还是需要看源码,就以java.io.ObjectOutputStream#writeObject写对象为入手点,跟踪源码会跟中到如下方法java.io.ObjectStreamClass#invokeWriteObject:

方法源码如下:

void invokeWriteObject(Object obj, ObjectOutputStream out)
throws IOException, UnsupportedOperationException
{
requireInitialized();
if (writeObjectMethod != null) {
try {
writeObjectMethod.invoke(obj, new Object[]{ out });
} catch (InvocationTargetException ex) {
Throwable th = ex.getTargetException();
if (th instanceof IOException) {
throw (IOException) th;
} else {
throwMiscException(th);
}
} catch (IllegalAccessException ex) {
// should not occur, as access checks have been suppressed
throw new InternalError(ex);
}
} else {
throw new UnsupportedOperationException();
}
}

  通过debug可以看到最终调用的是java.util.ArrayList#writeObject ,java.util.ArrayList#writeObject源码如下:

private void writeObject(java.io.ObjectOutputStream s)
throws java.io.IOException{
// Write out element count, and any hidden stuff
int expectedModCount = modCount;
s.defaultWriteObject(); // Write out size as capacity for behavioural compatibility with clone()
s.writeInt(size); // 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();
}
}ke  

可以看出最终将elementData写出去了。反序列化同理不在分析。

重点来了,name为什么JDK需要这么做呢?原因如下:

JDK为什么不直接用elementData来序列化,而采用上诉的方式来实现序列化呢?原因在于elementData是一个缓存数组,它通常会预留一些容量,等容量不足时再扩充容量,那么有些空间可能就没有实际存储元素,采用上诉的方式来实现序列化时,就可以保证只序列化实际存储的那些元素,而不是整个数组,从而节省空间和时间。

小提示:

java.io.ObjectOutputStream#writeObject中的enableOverride字段可以自行实现writeObjectOverride方法,对于enableOverride=true需要通过实现ObjectOutputStream的子类实现自定义写对象。

不要以为字段以transient修饰的话就一定不会被序列化的更多相关文章

  1. java transient修饰符

    1)一旦变量被transient修饰,变量将不再是对象持久化的一部分,该变量内容在序列化后无法获得访问. 2)transient关键字只能修饰变量,而不能修饰方法和类.注意,本地变量是不能被trans ...

  2. Transient修饰符的使用

    如果一个类没有继承Serilizable接口,那么它就不能被序列化,写入文件的时候会报异常.如果一个类继承了Serilizable接口,那么这个类的所有属性和方法都可以自动被序列化,而现实中我们又希望 ...

  3. transient修饰符的作用

    transient修饰符的作用: entity实体类: package com.baidu.entity; import com.fasterxml.jackson.annotation.JsonIg ...

  4. 【Hibernate学习笔记-5.1】使用@Transient修饰不想持久保存的属性

     作者:ssslinppp       1. 摘要 在默认情况下,持久化类的所有属性会自动映射到数据表的数据列.如果在实际应用中不想持久化保存某些属性,则可以考虑使用@Transient来修饰他们. ...

  5. 原!上线遇到的问题, java序列化关键字transient 修饰的属性变成null了

    1.问题描述: 某个功能点,user对象 放入session,后再另外地方取出,结果某个字段没有了.再本地和测试环境都是ok的,但是线上环境就是不行. 后来看到这个user对象的那个属性是加了tran ...

  6. 关于Java中的transient关键字

    Java中的transient关键字是在序列化时候用的,如果用transient修饰变量,那么该变量不会被序列化. 下面的例子中创建了一个Student类,有三个成员变量:id,name,age.ag ...

  7. [转]Gson过滤字段

    原文地址:http://my.oschina.net/orgsky/blog/368768 摘要 Gson过滤字段 Gson过滤字段 Gson 过滤 字段 属性 目录[-] 最简单的用法 方法1:排除 ...

  8. GSON使用笔记(1) -- 序列化时排除字段的几种方式

    http://blog.csdn.net/zxhoo/article/details/21471005 GSON是Google发布的JSON序列化/反序列化工具,非常容易使用.本文简要讨论在使用GSO ...

  9. 小伙子,你真的搞懂 transient 关键字了吗?

    先解释下什么是序列化 我们的对象并不只是存在内存中,还需要传输网络,或者保存起来下次再加载出来用,所以需要Java序列化技术. Java序列化技术正是将对象转变成一串由二进制字节组成的数组,可以通过将 ...

随机推荐

  1. angularjs学习第二天笔记---过滤器

    您好,我是一名后端开发工程师,由于工作需要,现在系统的从0开始学习前端js框架之angular,每天把学习的一些心得分享出来,如果有什么说的不对的地方,请多多指正,多多包涵我这个前端菜鸟,欢迎大家的点 ...

  2. JavaSE Collections类 , Iterator迭代器 , 增强for循环

    Collections 它是集合的工具类,为集合体系扩展了一些其他的方法.类中都是静态的方法,可以使用类名直接调用. 可变参数 在JDK1.5之后,如果我们定义一个方法需要接受多个参数,并且多个参数类 ...

  3. Java - List总结

    Java提高篇(三二)-----List总结 前面LZ已经充分介绍了有关于List接口的大部分知识,如ArrayList.LinkedList.Vector.Stack,通过这几个知识点可以对List ...

  4. 理解JVM之垃圾收集器概述

    前言 很多人将垃圾收集(Garbage Collection)视为Java的伴生产物,实际1960年诞生的Lisp是第一门真正使用内存动态分配与垃圾手机技术的语言.在目前看来,内存的动态分配与内存回收 ...

  5. apache伪静态原理图

  6. Python 并发编程(管道,事件,信号量,进程池)

    管道 Conn1,conn2 = Pipe() Conn1.recv() Conn1.send() 数据接收一次就没有了 from multiprocessing import Process,Pip ...

  7. FineReport新增多项目甘特图示例及操作

    1.描述 我们在做报表的时候,往往想体现其中随着时间的变化而产生的项目进度的变化和其他相关的系统进展,每当这种时候甘特图便是其中的不二之选.FineReport新增的多项目甘特图可以说是满足了大多数的 ...

  8. DOS中的ECHO命令详解

    1. 作为控制批处理命令在执行时是否显示命令行自身的开关  格式:ECHO [ON|OFF]  如果想关闭“ECHO OFF”命令行自身的显示,则需要在该命令行前加上“@”.  2. 显示当前ECHO ...

  9. Expo大作战(五)--expo中app.json 文件的配置信息

    简要:本系列文章讲会对expo进行全面的介绍,本人从2017年6月份接触expo以来,对expo的研究断断续续,一路走来将近10个月,废话不多说,接下来你看到内容,讲全部来与官网 我猜去全部机翻+个人 ...

  10. CSS3 中的 box-sizing属性

    语法: box-sizing: content-text | border-box | inherit; content-box(默认): 宽度和高度分别应用元素的内容框:在宽度和高度之外绘制元素的内 ...