引言
万物皆对象,在我们程序运行中,对象只要在引用链上存在引用,那么它就会一直存在。但是当我们程序结束的时候,那么对象就会消亡。那么在jvm不运行的时候我们仍能够保存下来是非常有意义的,在java中可以用序列化来实现。序列化其实也是IO系统中的一部分。在本篇博文中,详细介绍对象序列化的概念,不同序列化的方式和结果,并给出相应的demo。注意本文所说的序列化包括序列化与反序列化。笔者目前整理的一些blog针对面试都是超高频出现的。大家可以点击链接:http://blog.csdn.net/u012403290
序列化概念
序列化是指把对象通过IO系统转化成字节从而存储在磁盘当中,需要的时候可以还原成对象。也就是对象持久化的一个方式。
序列化意义
对象的生命周期是随着引用存在的,如果引用失效或者程序结束,那么这个对象就不复存在。但是我们可以通过序列化的方式把对象转成字节流从而存储在磁盘当中,在任何我们需要的时候再从新恢复成一个完整的对象。换句话说,就是对象持久化存储。
在我们网络通信的过程中,我们可以把对象序列化之后把它放入网络通信当中,这就弥补了不同操作系统之间的差异。不管你是从什么机器上序列化产生的字节流,在任意存在jvm虚拟机的情况下都可以从新转化成对象。
序列化设计IO
在序列化的过程中,根本上其实是一套IO操作,这个IO操作主要针对的就是对象。在IO系统中我们用ObjectInputStream与ObjectOutputStream来实现。在这两个对象流中存在两个方法readObejct和writeObject来实现对象的序列化输出和反序列化写入。
序列化方式
序列化是通过IO流来实现的,但是如果要序列化某一个对象,那么这个对象必须要实现了Serializable或Externalizable接口,否则在IO流操作的时候会抛出异常。
也就是说序列化对象存在两种方式:①Serializable;②Externalizable。那么这两个到底有什么区别呢?对于前者来说是对象的全自动序列化,它对对象中的所有的属性都会序列化,除却transient关键字标记的属性。对于后者来说,必须自己控制序列化过程,也就是说必须实现readExternal方法与writeExternal方法来控制序列化进行,同时后者反序列化的过程中,必须要执行对象的默认构造函数,所以说如果对象不存在可以调用的默认构造函数,那么就会抛错。
后面会详细介绍两者序列化的不同。
对象网
对象网是指序列化对象中对象之间引用的关系。比如说我序列化了A对象,A对象引用了B对象,B对象引用了C对象。那么在序列化之后这个对象之间的关系也是一同会写入字节流中进行持久化。在我们反序列化的过程中,能完整的还原出他们对象之间的关系。
transient关键字
transient是java的关键字,它表示在对象序列化的过程中,我们可以标记某一个敏感的属性,要求它在序列化的过程中唯独对这个属性不序列化,也就是说不把这个敏感属性持久化。
比如说在用户系统当中,我们需要对用户进行序列化存储后进行通信,但是我们不希望暴露这个用户的密码属性,那么我们就可以对密码这个属性进行transient关键字标记:
private transient String password;
Serializable序列化
在此处的代码需要体现出以下关键点:①对象的序列化和反序列化;②transient标记属性不会序列化;③能体现出对象的对象网关系;④反序列化不需要调用任何构造函数
假设存在一个用户体系(user类),他们有自己各自的兴趣(interest类)。在用户体系中我们不希望在序列化的过程中暴露password字段,所以我们用transient标记它。接着我们对着两个类的构造函数选择包级别私有,如果反序列化需要调用构造函数那么就会抛错。同时在两个类中我们都重写toString方法,在测试的时候方便打印出完整的信息。下面就是这两个类:
package com.brickworkers.io;
import java.io.Serializable;
public class User implements Serializable{
private static final long serialVersionUID = 3667335206886584270L;
private String name;
private String phone;
private transient String password;
private Interest interest;
//无参构造函数
User() {
name = "brickworker";
phone = "157110";
password = "123456";
}
User(String name, String phone, String password){
this.name = name;
this.password = password;
this.phone = phone;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public Interest getInterest() {
return interest;
}
public void setInterest(Interest interest) {
this.interest = interest;
}
@Override
public String toString() {
return &#