java之序列化与反序列化
序列化与反序列化
1、什么是序列化与反序列化
序列化:将对象转换为字节流或json、xml文本格式的过程叫序列化。
反序列化:将字节流转换为对象的过程叫反序列化
2、为什么要序列化
因为对象只有转化为字节流才能进行传输和持久化。
3、序列化方式
1.使用java原生序列化方式
将类实现serializable接口,并且记得要添加一个serializableID的属性。
举个例子:我们现在要将某个对象写到磁盘中的某个文件,那么我们需要将这个对象序列化为字节流,然后才能写入到文件中。
序列化步骤:
- 步骤一:创建一个ObjectOutputStream输出流;
- 步骤二:调用ObjectOutputStream对象的writeObject输出可序列化对象。
public class Person implements Serializable {
private String name;
private int age;
//我不提供无参构造器
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
public class WriteObject {
public static void main(String[] args) {
try (//创建一个ObjectOutputStream输出流
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("object.txt"))) {
//将对象序列化到文件
Person person = new Person("9龙", 23);
oos.writeObject(person);
} catch (Exception e) {
e.printStackTrace();
}
}
}
反序列化步骤:
- 步骤一:创建一个ObjectInputStream输入流;
- 步骤二:调用ObjectInputStream对象的readObject()得到序列化的对象。
public class Person implements Serializable {
private String name;
private int age;
//我不提供无参构造器
public Person(String name, int age) {
System.out.println("反序列化,你调用我了吗?");
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
public class ReadObject {
public static void main(String[] args) {
try (//创建一个ObjectInputStream输入流
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("person.txt"))) {
//进行反序列化成Object对象,并强转成Person类型。
Person brady = (Person) ois.readObject();
System.out.println(brady);
} catch (Exception e) {
e.printStackTrace();
}
}
}
//输出结果
//Person{name='9龙', age=23}
2.由redis案例进一步体会序列化
**key和value都使用默认的jdk序列化器:**可以发现这个序列化器底层实现序列化与我们上面举的例子方法类似,都是使用ObjectOutputStream,将对象转化为字节流。


key使用String序列化器(将字符串转化为字节流),value使用json序列化器(将对象转化为json):


因为使用json序列化器很明显存在问题,就是json中还记录了全类名的信息。如果要实现json自动化的转为对象这个全类名又是不可避免的。为了节省空间,对于value我们不使用json序列化器进行序列化,我们选key和value都使用string序列化器。如果value是一个对象,那么我们需要将对象变成String类型,可以想到json就是String类型,因此我们将对象转化为json形式,然后让string序列化器进行序列化写入redis。反序列化时,再将字节流转化为字符串。
string序列化器就是将字符串转换为字节数组然后存入redis中,由于字符串底层就等价于字节数组,因此我们在redis中看到的字节数组就是和我们看到的字符串是一样的。

4、对于原生序列化注意的点
1.实现 Serializable 接口的类建议设置 serialVersionUID 字段值。
原因是如果不设置的话,序列化时会为这个被序列化的类生成一个serialVersionUID ,并记录在字节流中。当反序列化时,会比对字节流中的serialVersionUID 与被序列化的类的serialVersionUID ,如果一样才能成功反序列化,否则失败。什么时候会失败呢?当我们修改这个类里的信息时,这个类的serialVersionUID就改变了,于是就无法反序列化了。
中的serialVersionUID 与被序列化的类的serialVersionUID ,如果一样才能成功反序列化,否则失败。什么时候会失败呢?当我们修改这个类里的信息时,这个类的serialVersionUID就改变了,于是就无法反序列化了。
2.Java 类通过实现 serializable 接口来实现该类对象的序列化,这个接口非常特殊,没有任何方法,只起标识作用。 只有被标识了,才能被序列化,没有被标识,就会报错。
更多推荐



所有评论(0)