一.序列化类实现Serializable接口
Serializable接口没有方法,更像是个标记。有了这个标记的Class就能被序列化机制处理。
ObjectOutputStream只能对Serializable接口的类的对象进行序列化。默认情况下,ObjectOutputStream按照默认方式序列化,这种序列化方式仅仅对对象的非transient的实例变量进行序列化,而不会序列化对象的transient的实例变量,也不会序列化静态变量。
当ObjectOutputStream按照默认方式反序列化时,具有如下特点:
1) 如果在内存中对象所属的类还没有被加载,那么会先加载并初始化这个类。如果在classpath中不存在相应的类文件,那么会抛出ClassNotFoundException;
2) 在反序列化时不会调用类的任何构造方法。
如果用户希望控制类的序列化方式(具体可参看二中的示例),可以在可序列化类中提供以下形式的writeObject()和readObject()方法。
private void writeObject(java.io.ObjectOutputStream out) throws IOException
private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException;
当 ObjectOutputStream对一个Customer对象进行序列化时,如果该对象具有writeObject()方法,那么就会执行这一方法, 否则就按默认方式序列化。在该对象的writeObjectt()方法中,可以先调用ObjectOutputStream的 defaultWriteObject()方法,使得对象输出流先执行默认的序列化操作。同理可得出反序列化的情况,不过这次是 defaultReadObject()方法。
有些对象中包含一些敏感信息,这些信息不宜对外公开。如果按照默认方式对它们序列化,那么它们的序列化数据在网络上传输时,可能会被不法份子窃取。对于这类信息,可以对它们进行加密后再序列化,在反序列化时则需要解密,再恢复为原来的信息。
默认的序列化方式会序列化整个对象图,这需要递归遍历对象图(也就是说对象中的基本类型属性和对象属性都能够被序列化)。如果对象图很复杂,递归遍历操作需要消耗很多的空间和时间,它的内部数据结构为双向列表。
在应用时,如果对某些成员变量都改为transient类型,将节省空间和时间,提高序列化的性能。
二. 实现Externalizable接口
Externalizable接口继承自Serializable接口,如果一个类实现了Externalizable接口,那么将完全由这个类控制自身的序列化行为。Externalizable接口声明了两个方法:
public void writeExternal(ObjectOutput out) throws IOException
public void readExternal(ObjectInput in) throws IOException , ClassNotFoundException
前者负责序列化操作,后者负责反序列化操作。
在对实现了Externalizable接口的类的对象进行反序列化时,会先调用类的不带参数的构造方法,这是有别于默认反序列方式的。如果把类的不 带参数的构造方法删除,或者把该构造方法的访问权限设置为private、默认或protected级别,会抛出 java.io.InvalidException: no valid constructor异常。
例如:
class Test implements Externalizable{ //Test类必须实现Externalizable接口
private String letterstates = "fanruijun";
private int num = 0;
public Test(){
}
public void writeExternal(ObjectOutput out) throws IOException {
out.writeObject(letterstates);
out.write(88); //在序列化的数据最后加个88
}
public void readExternal(ObjectInput in) throws IOException,
ClassNotFoundException {
letterstates = (String)in.readObject();
num = in.read(); //把数字88加进来
}
public void putOut(){ //测试
System.out.println(letterstates +num);
}
}
序列化上面的Test类:AppTest
public class AppTest {
private void saveGame(){
Test m = new Test();
if (m != null){
try{
FileOutputStream ostream = new FileOutputStream("t.txt");
ObjectOutputStream p = new ObjectOutputStream(ostream);
p.writeObject(m); //writeExternal()自动执行
p.flush();
ostream.close();
} catch (IOException ioe) {
System.out.println ("Error saving file:");
System.out.println (ioe.getMessage());
}
}
}
private void loadGame(){
try{
FileInputStream instream = new FileInputStream("t.txt");
ObjectInputStream p = new ObjectInputStream(instream);
Test m = (Test)p.readObject();//readExternal()自动执行
m.putOut();
instream.close();
} catch (Exception e) {
System.out.println ("Error loading file:");
System.out.println (e.getMessage());
}
}
public static void main(String[] args){
new AppTest().saveGame();
new AppTest().loadGame();
}}
运行结果:
D:\test\basic>javac AppTest.java
D:\test\basic>javac Test.java
D:\test\basic>java AppTest
fanruijun88
三. 可序列化类的不同版本的序列化兼容性
凡是实现Serializable接口的类都有一个表示序列化版本标识符的静态long类型变量:
private static final long serialVersionUID;
如果没有设置这个值,你在序列化一个对象之后,改动了该类的字段或者方法名之类的,那如果你再反序列化想取出之前的那个对象时就可能会抛出异常,因为你改 动了类中间的信息,serialVersionUID是根据类名、接口名、成员方法及属性等来生成一个64位的哈希字段,当修改后的类去反序列化的时候发 现该类的serialVersionUID值和之前保存在问价中的serialVersionUID值不一致,所以就会抛出异常。 而显示的设置serialVersionUID值就可以保证版本的兼容性,如果你在类中写上了这个值,就算类变动了,它反序列化的时候也能和文件中的原值 匹配上。而新增的值则会设置成null,删除的值则不会显示。
默认serialVersionUID的取值是Java运行时环境根据类的内部细节自动生成的。如果对类的源代码作了修改,再重新编译,新生成的类文件的serialVersionUID的取值有可能也会发生变化。
类的serialVersionUID的默认值完全依赖于Java编译器的实现,对于同一个类,用不同的Java编译器编译,有可能会导致不同的
serialVersionUID,也有可能相同。为了提高哦啊serialVersionUID的独立性和确定性,强烈建议在一个可序列化类中显示的定
义serialVersionUID,为它赋予明确的值。显式地定义serialVersionUID有两种用途:
1)
在某些场合,希望类的不同版本对序列化兼容,因此需要确保类的不同版本具有相同的serialVersionUID;
2)
在某些场合,不希望类的不同版本对序列化兼容,因此需要确保类的不同版本具有不同的serialVersionUID。
- Java 序列化和反序列化(二)Serializable 源码分析 - 1
目录 Java 序列化和反序列化(二)Serializable 源码分析 - 1 1. Java 序列化接口 2. ObjectOutputStream 源码分析 2.1 ObjectOutputSt ...
- Hadoop基础-序列化与反序列化(实现Writable接口)
Hadoop基础-序列化与反序列化(实现Writable接口) 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.序列化简介 1>.什么是序列化 序列化也称串行化,是将结构化 ...
- PHP序列化与反序列化学习
序列化与反序列化学习 把对象转换为字节序列的过程称为对象的序列化:把字节序列恢复为对象的过程称为对象的反序列化. <?php class UserInfo { public $name = &q ...
- Java序列化与反序列化学习(一)
一.序列化与反序列化概述 当两个进程在进行远程通信时,彼此可以发送各种类型的数据.无论是何种类型的数据,都会以二进制序列的形式在网络上传送.发送方需要把这个Java对象转换为字节序列,才能在网 ...
- JAVA对象序列化和反序列化学习
JAVA序列化就是将JAVA对象转化为字节序列的过程,而JAVA反序列化就是将字节序列转化为JAVA对象的过程. 这一过程是通过JAVA虚拟机独立完成,所以一个对象序列化后可以在任意时间和任意机器上反 ...
- java中的序列化和反序列化学习笔记
须要序列化的Person类: package cn.itcast_07; import java.io.Serializable; /* * NotSerializableException:未序列化 ...
- Java序列化与反序列化学习(三):序列化机制与原理
Java序列化算法透析 Serialization(序列化)是一种将对象以一连串的字节描述的过程:反序列化deserialization是一种将这些字节重建成一个对象的 过程.Java序列化API提供 ...
- Java 对象序列化和反序列化 (实现 Serializable 接口)
序列化和反序列化的概念 把对象转换为字节序列的过程称为对象的序列化. 把字节序列恢复为对象的过程称为对象的反序列化. 对象的序列化主要有两种用途: 1) 把对象的字节序列永久地保存到硬盘上,通常存放 ...
- php序列化和反序列化学习
1.什么是序列化 序列化说通俗点就是把一个对象变成可以传输的字符串. 1.举个例子,不知道大家知不知道json格式,这就是一种序列化,有可能就是通过array序列化而来的.而反序列化就是把那串可以传输 ...
随机推荐
- luci范例
转自:http://www.cnblogs.com/souroot/p/4511760.html LuCI (Lua Configiration Interface) 是OpenWRT 的Web 管理 ...
- H5 manifest离线缓存
请跳转我的有道云笔记查看: http://note.youdao.com/noteshare?id=caaf067c6e38820ba8f87b212c2327a9&sub=23E0F8F7A ...
- 深入理解Java中为什么内部类可以访问外部类的成员
内部类简介 虽然Java是一门相对比较简单的编程语言,但是对于初学者, 还是有很多东西感觉云里雾里, 理解的不是很清晰.内部类就是一个经常让初学者感到迷惑的特性. 即使现在我自认为Java学的不错了, ...
- unity color space 选取
https://unity3d.com/cn/learn/tutorials/topics/graphics/choosing-color-space https://docs.unity3d.com ...
- Java笔记15:多线程
Java实现多线程有两种方式:一是继承Thread类:二是实现Runable接口. 一.Thread实现 publicclass ThreadDemo2 { publicstaticvoid main ...
- LInux 分割合并文件
有两种方式, 第一种使用dd命令 第二种使用split dd命令是linux下一个非常有用的磁盘命令.它可以将指定大小的块拷贝成一个文件,并在拷贝的同时执行指定的转换.UNIX已经提供了文件切割功能, ...
- [Angular] Angular i18n Alternative Expressions Support (select)
For example we have those code: <div class="course-category" [ngSwitch]="course.ca ...
- STL_算法_区间的比較(equal、mismatch、 lexicographical_compare)
C++ Primer 学习中.. . 简单记录下我的学习过程 (代码为主) //全部容器适用 equal(b,e,b2) //用来比較第一个容器[b,e)和第二个容器b2开头,是否相等 e ...
- Discuz常见小问题2-如何在新建的页面上只显示一部分板块
切换到论坛-版块管理,记住要只显示的板块的gid(比如我的是36) 为某个主导航设置一个单独的php页面(名字自己取) 如果这个页面内容跟首页forum.php完全一样,只是第三行增加了一句话 ...
- Django 学习记录
这是我自己理解并自己画的,django 请求示意图,表示了它的组织方式. project manage.py: 主要工具文件 settings.py: 配置文件 urls.py: url 定义及其指向 ...