文档章节

(1)java序列化--java.io.Serializable接口解析

sumekey
 sumekey
发布于 2011/09/07 17:45
字数 925
阅读 308
收藏 3

【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>>

(PS:本文为作者原著,如需转载,请注明出处-_^)      

    使用java以来,序列化随处可见,至于为什么要用序列化、序列化能解决什么问题,作为一个普通的码农,一般不怎么会去深入研究,由于最近在看mina和公司内部涉及到nio框架的一些源码,里面涉及到hession、java这两种序列化,至于hession序列化为什么会诞生以及在apache项目中使用如此广泛,以及java本身序列化存在哪些缺陷,甚是不解,为了解答上面抛出来的疑惑,以及进一步了解java的序列化机制,这里开个小头,从java的序列化接口Serializable开始说起

jdk包里的Serializable接口的注释主要说明了以下几点:

1.类通过实现Serializable接口来启用序列化,否则该类的任何状态将无法被序列化,同时也无法用于反序列化

2.若继承的父类没有实现Serializable接口,但是又想让子类可序列化,有三个注意事项:

    a).子类实现Serializable接口

    b).子类必须有可访问的无参构造方法,用于保存和恢复父类的public或protected或同包下的package字段的状态,否则在序列化或反序列化时会抛出RuntimeException异常

    c).对于序列化后的子类,在进行反序列化时,理论上无法初始化父类中private(不可访问)对象变量的状态或值

3.在对可序列化类中的属性进行序列化时,如果遇到不可序列化的对象变量,此时会针对不可序列化的类抛出NotSerializableException异常

4.对于可序列化的非数组类,强烈建议显示声明static型、long型、final型serialVersionUID字段用于标识当前序列化类的版本号,否则在跨操作系统、跨编译器之间进行序列化和反序列化时容易出现InvalidClassException异常

5.对于可序列化类中的static、transient对象变量,在序列化时无法保存其状态或值,static对象变量在反序列化时取得的值为当前jvm中对应类中对应static变量的值,而transient(瞬态)关键字则一般用于标识那些在序列化时不需要传递的状态变量

 简单的测试代码:

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

/**
 * 序列化测试
 * 
 * @author sume
 * 
 */
public class SerializableImpl implements Serializable {

	private static final long serialVersionUID = -6433786313435044319L;

	static String staticVal = "static1";
	transient String transientVal = "transient1";
	String val = "val1";

	/**
	 * main
	 */
	public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException {
		// 序列化
		SerializableImpl sila1 = new SerializableImpl();
		ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("Serializable.txt"));
		objectOutputStream.writeObject(sila1);
		objectOutputStream.close();

		// 反序列化
		SerializableImpl.staticVal = "static2";
		ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("Serializable.txt"));
		SerializableImpl sila2 = (SerializableImpl) objectInputStream.readObject();
		objectInputStream.close();

		// 比较各个属性的值
		System.out.println(sila2.staticVal);
		System.out.println(sila2.transientVal);
		System.out.println(sila2.val);
	}
}
输出结果:

static2
null
val1

从输出结果可以看出:

1.反序列化后类中static型变量staticVal的值为当前jvm中对应static变量的值,为:static2,而不是序列化时的值:static1

2.transient关键字标识的变量的状态并没有在序列化中被保存,因此反序列化后

transientVal变量的值为null

3.第三个为常见的对象状态在序列化和反序列化过程中的传递

简单印证了前面所说的几点内容

另外:对于在序列化和反序列化过程中需要对类进行特殊处理或需要指定替代对象的操作,

本文没有涉及到,会在后面进一步讨论时给出


© 著作权归作者所有

sumekey
粉丝 0
博文 5
码字总数 2604
作品 0
杭州
私信 提问
hibernate 对象为什么需要实现 Serializable接口

注意区分持久化和序列化,持久化是把对象中的信息转换为数据库中的表来存储;序列化是将对象(java对象)直接变成字符串等流,存储到硬盘上,不涉及数据库表。 序列化的目的主要是方便直接传...

柠檬的橘子
2017/03/16
102
0
Java: serialVersionUID的作用

serialVersionUID 用来表明类的不同版本间的兼容性 简单来说,Java的序列化机制是通过在运行时判断类的serialVersionUID来验证版本一致性的。在进行反序列化时,JVM会把传来 的字节流中的ser...

曾赛
2010/07/29
1K
0
serialVersionUID 的作用

serialVersionUID 用来表明类的不同版本间的兼容性 简单来说,Java的序列化机制是通过在运行时判断类的serialVersionUID来验证版本一致性的。在进行反序列化时,JVM会把传来的字节流中的ser...

Sammy夏
2012/08/08
156
5
java.io.Serializable浅析

 Java API中java.io.Serializable接口源码: 1 public interface Serializable {2 }   类通过实现java.io.Serializable接口可以启用其序列化功能。未实现次接口的类无法使其任何状态序列化...

偶尔诗文
2015/08/16
64
0
Java入门教程之图书管理系统(由简入繁)(二)

作者:AlexTan E-mail: alextanbz@gmai.com 上一篇博客我们介绍了用数组的方式来实现图书管理系统,但是用数组实现的方式有两个主要的缺点就是:1. 查找和删除比较麻烦;2. SIZE得固定,SIZ...

AlexTan_
2017/03/23
0
0

没有更多内容

加载失败,请刷新页面

加载更多

JVM性能调优的6大步骤,及关键调优参数详解

JVM内存调优 对JVM内存的系统级的调优主要的目的是减少GC的频率和Full GC的次数。 1.Full GC 会对整个堆进行整理,包括Young、Tenured和Perm。Full GC因为需要对整个堆进行回收,所以比较慢,...

一只会编程的狼
15分钟前
6
0
并发和并行性有什么区别?

并发和并行性有什么区别? 示例被赞赏。 #1楼 并发性:具有共享资源潜力的多个执行流 例如:两个线程争用一个I / O端口。 平行主义:将问题分成多个相似的块。 例如:通过在文件的每半部分上...

javail
17分钟前
4
0
(推荐使用)提高开发效率工具集合

提高开发效率工具集合(推荐使用) 一、Hutool工具类 官网地址:https://www.hutool.cn/ Github地址:https://github.com/looly/hutool/ Gitee 地址:https://gitee.com/loolly/hutool/ 文档参...

明德先生
21分钟前
4
0
java并发-缓存一致性协议和内存屏障的思考和理解

################这是之前的思考 内存屏障只是保证清空流水线,如何保证高速缓存的内容更新到最新或刷新到主存呢?这个问题突然想到了,不知道这个需要怎回答。 内存屏障保证的CPU执行执行序...

萧默
24分钟前
5
0
类型名称后面的括号是否与new有所不同?

如果“测试”是普通类,则之间是否有任何区别: Test* test = new Test; 和 Test* test = new Test(); #1楼 new Thing(); 很明显,您想要一个构造函数,而new Thing; 表示您不介意是否未调...

技术盛宴
48分钟前
5
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部