【技术累积】【点】【java】【21】序列化二三事
基础概念
- 把对象等转为二进制进行传输的是序列化,反之为反序列化;
- 应用场景一般为读写文件,传输数据/接口调用;
Externalizable和Serializable
java的序列化方式有两种;
Serializable是常用的方法,实现方法为
class User implements Serializable {
private static final long serialVersionUID = -3226152074589523662L;
...
}
实现接口,并且最好有序列化ID;
Externalizable是Serializable的子类,但不会自动化序列化,需要调用方法实现序列化;
idea自动生成序列化ID
打开设置中的检测,然后每次有需要序列化的,生成一个Long型即可
序列化ID也可以是自定义的,比如简单的1L,只要调用方和被调用方约定一致即可;
transient关键字
- transient修饰的变量,不会被序列化;
- 静态变量一定不会被序列化(类的属性而不是对象的属性值)
- 一旦变量被transient修饰,变量将不再是对象持久化的一部分,该变量内容在序列化后无法获得访问;
- transient关键字只能修饰变量,而不能修饰方法和类;
- 使用Externalizable可以序列化transient修饰的变量
import lombok.*;
import lombok.extern.slf4j.Slf4j;
import org.testng.annotations.Test;
import java.io.*;
@Slf4j
public class TestTransient {
// private static final long serialVersionUID = 8204877978271765366L;
@Test
public void testTransi(){
User user = new User("andy","123456");
log.info("Before serializable,user={}",user.toString());
try {
ObjectOutputStream os = new ObjectOutputStream(new FileOutputStream("D:/user.txt"));
os.writeObject(user);
os.flush();
os.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
ObjectInputStream is = new ObjectInputStream(new FileInputStream("D:/user.txt"));
user = (User) is.readObject();
is.close();
log.info("After serializable,username={},pwd={}",user.getUsername(),user.getPassword());
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
@Setter
@Getter
@AllArgsConstructor
@NoArgsConstructor
@ToString
static class User implements Serializable {
private static final long serialVersionUID = -3226152074589523662L;
String username;
transient String password;
}
}
还需要注意的几个问题
- 虚拟机是否允许反序列化,不仅取决于类路径和功能代码是否一致,一个非常重要的一点是两个类的序列化 ID 是否一致
- 要想将父类对象也序列化,就需要让父类也实现Serializable 接口。如果父类不实现的话的,就需要有默认的无参的构造函数
- 可以尝试使用序列化实现加密控制等(Override),参考RMI技术
- 注意往一个文件中多次写入同一个对象的情况
Java 序列化机制为了节省磁盘空间,具有特定的存储规则,当写入文件的为同一对象时,并不会再将对象的内容进行存储,而只是再次存储一份引用,上面增加的 5 字节的存储空间就是新增引用和一些控制信息的空间。反序列化时,恢复引用关系,使得清单 3 中的 t1 和 t2 指向唯一的对象,二者相等,输出 true。该存储规则极大的节省了存储空间。