序列化
1.什么是序列化?反序列化?
序列化是指将对象编码转化成可以存储或传输的字节流。反序列化就是将字节流重新还原为相等的对象。
2.序列化的特性。
- 在jvm中,一些对象没有被回收时,只有jvm处于运行状态的时候,对象才可能存在,一旦jvm停止,这些对象也就随之消失。而序列化过后的对象会依然以字节流的形式存在于磁盘之上,当下次java应用程序再次启动时又可以通过反序列化创建对象。
- 序列化后的对象可以从一个正在运行中的虚拟机中传输到另一个虚拟机中。
- 对象持久化。在真实应用场景中需要将对象持久化,并且在需要的时候将对象重新读取出来,java序列化可以帮助我们实现这些功能。
- 必须实现java.io.Serializable接口才能进行序列化或者反序列化
- 不能持久化静态变量,序列化只能保存对象的状态,而静态变量是类的状态
3.序列化以及反序列化相关的类和接口
java为了方便实现序列化和反序列化提供了一套方便的api来支持,其中包括以下的接口和类。
java.io.Serializable
java.io.Externalizable
objectOutput
objectInput
ObjectInputStream
ObjectOutputStream
4.Serialization接口详解
-
java通过Serializable来实现序列化功能,如果为实现该接口的类,将无法将任何对象状态或者信息转化成序列化对象。
-
如果在实现对一个对象实现序列化时,这个对象没有实现java.io.Serializable接口,则会抛出NotSerializationException异常。
-
java.io.Serializable接口实现demo:
User1.java
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import java.io.Serializable;
/**
* @Author Xiao Liu
* @Date 2019/8/19 10:23
* @Version 1.0
*/
public class User1 implements Serializable {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE)
.append("name",name)
.append("age",age)
.toString();
}
}
public static void main(String args []) throws IOException, ClassNotFoundException {
User1 user1= new User1();
user1.setName("KEY.Liu");
user1.setAge(22);
System.out.println(user1.toString());
//序列化
ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("demoOp"));
objectOutputStream.writeObject(user1);
objectOutputStream.close();
//反序列化
File file =new File("demoOp");
ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream(file));
User1 user= (User1)objectInputStream.readObject();
System.out.println(user.toString());
}
输出结果:
User1@2f0e140b[ name=KEY.Liu age=22 ] User1@b1bc7ed[ name=KEY.Liu age=22 ]
- java.io.Externalizable接口实现序列化
java.io.Externalizable实现了Serializable,新增了两个方法ExternalWrite()和ExternalRead(),当使用这两个方法进行重写时需要对他们进行重写。这两个方法定义了序列化与反序列化实现的细节。当没有重写时,输出内容会为空。
User2.java
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
/**
* @Author Xiao Liu
* @Date 2019/8/19 10:36
* @Version 1.0
*/
public class User2 implements Externalizable {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public void writeExternal(ObjectOutput out) throws IOException {
out.writeObject(name);
out.writeInt(age);
}
@Override
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
name = (String)in.readObject();
age = in.read();
}
@Override
public String toString() {
return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE)
.append("name",name)
.append("age",age)
.toString();
}
}
public void externalizableTest() throws IOException, ClassNotFoundException {
User2 user2 = new User2();
user2.setName("KEY.L");
user2.setAge(23);
System.out.println(user2.toString());
//序列化
ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("demoOp2"));
objectOutputStream.writeObject(user2);
objectOutputStream.close();
//反序列化
File file =new File("demoOp2");
ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream(file));
User2 user= (User2)objectInputStream.readObject();
// User1 user1 =(User1)objectInputStream.readObject();
System.out.println(user.toString());
// System.out.println(user1.toString());
objectInputStream.close();
}
输出结果:
User2@17d10166[ name=KEY.L age=23 ] User2@39a054a5[ name=KEY.L age=0 ]
5.Transient关键字的作用
Transient关键字的作用是控制变量的序列化,在变量声明前加上该关键字,可以组织该变量被序列化到文件中,在反序列化后,Transient变量的值被设为初始值。如int型的是0,对象是null。