序列化与反序列化的简单粗暴解释
一、内容简介
1.什么是序列化和反序列化?
(1)序列化就是把Java对象转化为字节流序列(二进制串)的过程
(2)反序列化就是把字节流(二进制串)恢复为Java对象的过程
2.为什么要进行序列化
我们知道,当两个进程需要通信的时候,可以发送各种类型的数据,包括文字、图片、音频和视频,但是这些数据都是以二进制的形式在网络上传输。所以当两个Java进程进行通信的时候,如何实现进程间对象的传送呢。这就需要用到序列化和反序列化了。一方面,发送方将这个Java对象转化为字节对象,然后在网络上传输。另一个方面,接收方需要从字节序列中恢复出Java对象。
3.好处
第一.利用序列化实现远程的通信,即在网络上传输信息。第二,可以实现数据的持久化,通过序列化可以把数据永久的保存到硬盘上。
二、Java类库中的序列化
Java.io.ObjectOutputStream代表对象输出流,它的WriteObject( object obj) 方法可以对指定的obj对象进行序列化,把得到的二进制串输入到指定的文件中。
与此相对应,Java.io.ObjectInputStream代表对象输入流,它的readObject(object obj)方法可以将读取的二进制串进行反序列化为Java对象,并且将其返回。
只有实现了Serializable接口的类才能够被序列化,所以一定要实现Serializable。跳进去你会发现,只有一个Serializable接口。
- <span style="font-family:KaiTi_GB2312;font-size:18px;"> * @author unascribed
- * @version 1.25, 11/17/05
- * @see java.io.ObjectOutputStream
- * @see java.io.ObjectInputStream
- * @see java.io.ObjectOutput
- * @see java.io.ObjectInput
- * @see java.io.Externalizable
- * @since JDK1.1
- */
- public interface Serializable {
- }</span>
2.对象序列化的步骤如下
(1)创建对象输入流,它可以包装一个其他类型的目标输入流,例如:文件输出流。
(2)通过对象输入流的writeObject()方法写对象。
3.对象的反序列化如下:
(1)创建对象输入流,同样的,可以包含其他类型的目标输出流,例如:文件输入流。
(2)通过对象输入流的readObject()方法读取对象。
4.实例
(1)创建User对象
- <span style="font-family:KaiTi_GB2312;font-size:18px;">/**
- * 用户
- * @author lizhenjuan
- */
- public class User implements java.io.Serializable{
- private static final long serialVersionUID = 1L;
- private Long id;
- private String name; // 真实姓名
- private String loginName; // 登录名
- private String description; // 说明
- }
- </span>
(2)序列化Use对象
- <span style="font-family:KaiTi_GB2312;font-size:18px;"> /**
- * User对象序列化测试代码
- * @throws FileNotFoundException
- * @throws IOException
- */
- @Test
- private static void SerializablePerson() throws Exception, FileNotFoundException, IOException{
- User user = new User();
- user.setName("lizhenjuan");
- user.setLoginName("lzh");
- user.setDescription("just test");
- //输出流,将对象输出到txt文件中
- ObjectOutputStream oo = new ObjectOutputStream(new FileOutputStream(new File("F:/User.txt")));
- oo.writeObject(user);
- System.out.println("序列化成功!");
- oo.close();
- }</span>
执行结果,是在F 盘下生成了User.txt文件。
(3)反序列化User对象
- <span style="font-family:KaiTi_GB2312;font-size:18px;">/**
- * 反序列化User对象,对去User.txt文件内容
- * @return
- * @throws Exception
- * @throws FileNotFoundException
- * @throws IOException
- * @throws ClassNotFoundException
- */
- private static User DeserializePerson() throws Exception,FileNotFoundException, IOException, ClassNotFoundException {
- ObjectInputStream ois=new ObjectInputStream(new FileInputStream(new File("F:/User.txt")));
- User user =(User)ois.readObject();
- System.out.println("User对象反序列化成功");
- return user;
- }
- //读取User.txt文件的内容
- public static void main(String[] args) throws Exception{
- User user = DeserializePerson(); //反序列化对象
- System.out.println(MessageFormat.format("name={0},loginName={1},description={2}",
- user.getName(),user.getLoginName(),user.getDescription()));
- }
- </span>
读取F盘User.txt文件内容,打印出来。
打印内容如下:
三、SerialVersionUID 的作用
1.两种类型
SerialVersionUID:意思是序列化的版本号,凡是实现序列化接口的类都会有一个表示序列化版本标识的静态变量。
SerialVersionUID的两种生成方式。
第一种
采用这种方式生成的SerialVersionUID是1L;
private static final long serialVersionUID = 1L;
第二种
这一种是根据类名称、接口名称、方法和属性来生成的。
private static final long serialVersionUID = 4603642343377807741L;
2.SerialVersionID作用是什么?
SerialVerssionID
保证在很多类中,某个类的编号是唯一的。如果在实体类中,没有显式声明SerialVersionID,那么java编译器会自动给你生成一个ID。如果要在序列化之后的实体中添加一个字段,那么序列化之后,就又会生成一个SerialVersionID
,于是就会出现两个序列化版本号不一致的错误。所以,我们在类中显式声明乐SerialVersionUID之后,就可以在序列化之后,增加或者删除一个字段,而不会影响到后期的还原。还原之后,可以使用。
类的serialVersionUID的默认值完全依赖于Java编译器的实现,对于同一个类,用不同的Java编译器编译,有可能会导致不同的
serialVersionUID,也有可能相同。为了提高serialVersionUID的独立性和确定性,强烈建议在一个可序列化类中显示的定义serialVersionUID,为它赋予明确的值。