在网上看到自己复习学过但不熟练的反序列化基础笔记,抄录并学习。
Java的序列化和反序列化
Java 提供了一种对象序列化的机制,该机制中,一个对象可以被表示为一个字节序列,该字节序列包括该对象的数据、有关对象的类型的信息和存储在对象中数据的类型。把字节序列恢复为对象的过程称为对象的反序列化。
- 序列化就是把对象的状态信息转换为字节序列(即可以存储或传输的形式)过程
- 反序列化即逆过程,由字节流还原成对象
位置: Java.io.ObjectOutputStream java.io.ObjectInputStream
序列化: ObjectOutputStream --> writeObject()该方法对参数指定的obj对象进行序列化,把字节序列写到一个目标输出流中,按Java的标准约定是给文件一个.ser扩展名。
反序列化: ObjectInputStream --> readObject() 该方法从一个源输入流中读取字节序列,再把它们反序列化为一个对象,并将其返回。
注:实现Serializable和Externalizable接口的类的对象才能被序列化。
并不是一个实现了序列化接口的类的所有字段及属性,都是可以序列化的:
- 如果该类有父类,则分两种情况来考虑:如果该父类已经实现了可序列化接口,则其父类的相应字段及属性的处理和该类相同;如果该类的父类没有实现可序列化接口,则该类的父类所有的字段属性将不会序列化,并且反序列化时会调用父类的默认构造函数来初始化父类的属性,而子类却不调用默认构造函数,而是直接从流中恢复属性的值。
- 如果该类的某个属性标识为static类型的,则该属性不能序列化。
- 如果该类的某个属性采用transient关键字标识,则该属性不能序列化。
Demo
一般方式
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.text.MessageFormat;
import java.io.Serializable;
class Person implements Serializable {
/**
* 序列化ID
*/
private static final long serialVersionUID = -5809782578272943999L;
private int age;
private String name;
private String sex;
public int getAge() {
return age;
}
public String getName() {
return name;
}
public String getSex() {
return sex;
}
public void setAge(int age) {
this.age = age;
}
public void setName(String name) {
this.name = name;
}
public void setSex(String sex) {
this.sex = sex;
}
}
/**
* ClassName: SerializeAndDeserialize
* Description: 测试对象的序列化和反序列
*/
public class SerializeDeserialize_readObject {
public static void main(String[] args) throws Exception {
SerializePerson();//序列化Person对象
Person p = DeserializePerson();//反序列Perons对象
System.out.println(MessageFormat.format("name={0},age={1},sex={2}",
p.getName(), p.getAge(), p.getSex()));
}
/**
* MethodName: SerializePerson
* Description: 序列化Person对象
*/
private static void SerializePerson() throws FileNotFoundException,
IOException {
Person person = new Person();
person.setName("ssooking");
person.setAge(20);
person.setSex("男");
// ObjectOutputStream 对象输出流,将Person对象存储到Person.txt文件中,完成对Person对象的序列化操作
ObjectOutputStream oo = new ObjectOutputStream(new FileOutputStream(
new File("Person.txt")));
oo.writeObject(person);
System.out.println("Person对象序列化成功!");
oo.close();
}
/**
* MethodName: DeserializePerson
* Description: 反序列Perons对象
*/
private static Person DeserializePerson() throws Exception, IOException {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(new File("Person.txt")));
/*
FileInputStream fis = new FileInputStream("Person.txt");
ObjectInputStream ois = new ObjectInputStream(fis);
*/
Person person = (Person) ois.readObject();
System.out.println("Person对象反序列化成功!");
return person;
}
}
自定义序列化的方式
public class SeriDemo1 implements Serializable {
private String name;
transient private String password;
// 瞬态,不可序列化状态,该字段的生命周期仅存于调用者的内存中
public SeriDemo1() {
}
public SeriDemo1(String name, String password) {
this.name = name;
this.password = password;
}
//模拟对密码进行加密
private String change(String password) {
return password + "minna";
}
//写入
private void writeObject(ObjectOutputStream outStream) throws IOException {
outStream.defaultWriteObject();
outStream.writeObject(change(password));
}
//读取
private void readObject(ObjectInputStream inStream) throws IOException,
ClassNotFoundException {
inStream.defaultReadObject();
String strPassowrd = (String) inStream.readObject();
//模拟对密码解密
password = strPassowrd.substring(0, strPassowrd.length() - 5);
}
//返回一个“以文本方式表示”此对象的字符串
public String toString() {
return "SeriDemo1 [name=" + name + ", password=" + password + "]";
}
//静态的main
public static void main(String[] args) throws Exception {
SeriDemo1 demo = new SeriDemo1("haom", "0123");
ByteArrayOutputStream buf = new ByteArrayOutputStream();
ObjectOutputStream out = new ObjectOutputStream(buf);
out.writeObject(demo);
ObjectInputStream in = new ObjectInputStream(new
ByteArrayInputStream(buf.toByteArray()));
demo = (SeriDemo1) in.readObject();
System.out.println(demo);
}
}