Serializable探究一二
2016-07-03 16:52
435 查看
序列化探究一二
Serializable原理seriaVersionUid的作用
自定义序列化及反序列化过程
磁盘保存文件,进程间数据交互,网络传输数据等都是先将数据转换为字节序列,收到字节序列后再转换为图片,视频或其他文件。
这一过程就需要序列化和反序列化的支持。Java中序列化是通过==ObjectOutputStream.writeObject()== 方法将Object转为字节序列后写到输出流中。反序列化是通过==ObjectInputStream.readObject()== 将字节序列转为一个对象。
先上代码:
1.定义一个User类,这个类先不继承Serializable
import java.io.Serializable; public class User implements Serializable{ private int id; private String name; private int age; private boolean sex; public User(int id,String name,int age,boolean sex){ this.id = id; this.name = name; this.age = age; this.sex = sex; } }
2.实现序列化
public static void enSerializable() throws IOException{ FileOutputStream fo = new FileOutputStream(new File("D:/user.txt")); ObjectOutputStream oo = new ObjectOutputStream(fo); oo.writeObject(new User(1,"wangliang",22,true)); oo.close(); }
3.反序列化实现
public static void deSerializable() throws IOException, ClassNotFoundException { FileInputStream fi = new FileInputStream(new File("D:/user.txt")); ObjectInputStream oi = new ObjectInputStream(fi); User user = (User)oi.readObject(); System.out.println("User对象反序列化成功!"+user.getName()+user.getAge()); }
运行报错: java.io.NotSerializableException
但是打开user.txt 发现里面已经写入了数据,虽然都是乱码。此时反序列化失败。
修改User类让其继承Serializable,正常序列化和反序列化。
serialVersionUID的作用
主要是为了类的兼容性。想象一下这种场景:
昨天将学生类的数据保存到了磁盘上,今天取数据之前要在学生类上多加一个字段,如果没有指定serialVersionUID,会报错,因为编译器认为这两个类不一致了。此时如果加上serialVersionUID可以正常反序列化。
通常有两种赋值方式,一种是1L,2L这种,另外一种是64位的Hash值,用那种看你,如果想保持向后兼容,就让serialVersionUID一致,否则改成不一样就好了。
自定义序列化及反序列化过程
方法一:若Student类仅仅实现了Serializable接口,则可以按照以下方式进行序列化和反序列化ObjectOutputStream采用默认的序列化方式,对Student对象的非transient的实例变量进行序列化。
ObjcetInputStream采用默认的反序列化方式,对对Student对象的非transient的实例变量进行反序列化。
方法二:若Student类仅仅实现了Serializable接口,并且还定义了readObject(ObjectInputStream in)和writeObject(ObjectOutputSteam out),则采用以下方式进行序列化与反序列化。
ObjectOutputStream调用Student对象的writeObject(ObjectOutputStream out)的方法进行序列化。
ObjectInputStream会调用Student对象的readObject(ObjectInputStream in)的方法进行反序列化。
方法三:若Student类实现了Externalnalizable接口,且Student类必须实现readExternal(ObjectInput in)和writeExternal(ObjectOutput out)方法,则按照以下方式进行序列化与反序列化。
ObjectOutputStream调用Student对象的writeExternal(ObjectOutput out))的方法进行序列化。
ObjectInputStream会调用Student对象的readExternal(ObjectInput in)的方法进行反序列化。
说明:
1.对于方法一:如果某个字段不想进行序列化和发序列化,那么对该字段加transient关键字修饰即可。
2.方法二和方法三都可以控制序列化和反序列化过程。不同的是方法二在readObject()和writeObject()中进行控制,而且这两个方法不一定必须实现;方法三readExternal()和writeExternal()必须实现,同时继承了 Externalizable接口后不会再执行readObject()和writeObject()方法。
3.自定义序列化过程在实际中用到的可能是控制反序列化后对象的字段顺序,以前项目中遇到过用字段来验签,结果每次序列化后字段顺序不一样导致验签不过,这个问题可以通过自定义序列化过程来解决。
* 继承Externalizable接口代码:*
@Override public void readExternal(ObjectInput arg0) throws IOException, ClassNotFoundException { // TODO Auto-generated method stub setAge(arg0.readInt()); setName((String)arg0.readObject()); setId(arg0.readInt()); setSex(arg0.readBoolean()); } @Override public void writeExternal(ObjectOutput arg0) throws IOException { // TODO Auto-generated method stub arg0.writeInt(getId()); arg0.writeObject(getName()); arg0.writeInt(getAge()); arg0.writeBoolean(isSex()); System.out.println("User对象序列化成功!"); }
相关文章推荐
- java对世界各个时区(TimeZone)的通用转换处理方法(转载)
- java-注解annotation
- java-模拟tomcat服务器
- java-用HttpURLConnection发送Http请求.
- java-WEB中的监听器Lisener
- Android IPC进程间通讯机制
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- 介绍一款信息管理系统的开源框架---jeecg
- 聚类算法之kmeans算法java版本
- java实现 PageRank算法
- PropertyChangeListener简单理解
- c++11 + SDL2 + ffmpeg +OpenAL + java = Android播放器
- 插入排序
- 冒泡排序
- 堆排序
- 快速排序
- 二叉查找树