一文带你解读Java序列化和反序列化机制
世界尽头与你 人气:0Java 提供了一种对象序列化的机制,该机制中,一个对象可以被表示为一个字节序列,该字节序列包括该对象的数据、有关对象的类型的信息和存储在对象中数据的类型。
将序列化对象写入文件之后,可以从文件中读取出来,并且对它进行反序列化,也就是说,对象的类型信息、对象的数据,还有对象中的数据类型可以用来在内存中新建对象。
整个过程都是 Java 虚拟机(JVM)独立的,也就是说,在一个平台上序列化的对象可以在另一个完全不同的平台上反序列化该对象。
类 ObjectInputStream 和 ObjectOutputStream 是高层次的数据流,它们包含反序列化和序列化对象的方法。
简单来说:
- 序列化: 将数据结构或对象转换成二进制字节流的过程
- 反序列化:将在序列化过程中所生成的二进制字节流转换成数据结构或者对象的过程
下面是序列化和反序列化常见应用场景:
- 对象在进行网络传输(比如远程方法调用 RPC 的时候)之前需要先被序列化,接收到序列化的对象之后需要再进行反序列化;
- 将对象存储到文件之前需要进行序列化,将对象从文件中读取出来需要进行反序列化;
- 将对象存储到数据库(如 Redis)之前需要用到序列化,将对象从缓存数据库中读取出来需要反序列化;
- 将对象存储到内存之前需要进行序列化,从内存中读取出来之后需要进行反序列化。
需要让某个对象支持序列化机制,需要保证该类是可序列化的:
该类必须实现以下两个接口之一:
- Serializable(优先选择)
- Externalizable
序列化演示:
Dog类:
// Dog类需要实现Serializable接口才可以支持序列化操作 class Dog implements Serializable { private String name; private int age; public Dog(String name, int age) { this.name = name; this.age = 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 "Dog{" + "name='" + name + '\'' + ", age=" + age + '}'; } }
/** * ObjectOutputStream进行序列化 */ @Test public void Out() throws IOException { String filePath = "D:\\data.dat"; ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(filePath)); oos.write(100); oos.writeBoolean(true); oos.writeChar('a'); oos.writeDouble(5.21); oos.writeUTF("IMUSTCTF"); oos.writeObject(new Dog("旺财",1)); oos.close(); System.out.println("数据序列化成功!"); }
反序列化演示:
反序列化类:
/** * ObjectInputStream反序列化 */ @Test public void Input() throws IOException, ClassNotFoundException { String filePath = "D:\\data.dat"; ObjectInputStream ois = new ObjectInputStream(new FileInputStream(filePath)); // 开始读取bat文件 // 注意:读取顺序要和序列化时的顺序一致! System.out.println(ois.readInt()); System.out.println(ois.readBoolean()); System.out.println(ois.readChar()); System.out.println(ois.readDouble()); System.out.println(ois.readUTF()); Object dog = ois.readObject(); System.out.println(dog); // 访问dog的私有属性 Dog dd = (Dog) dog; System.out.println(dd.getName()); // 关闭外层流 ois.close(); }
对象处理流使用细节:
- 请按照序列化的顺序进行反序列化
- 序列化的类中建议添加如下语句:(为了提高版本的兼容性)
@Serial private static final long serialVersionUID = 1L;
序列化具有可继承性,父类实现了序列化,则其子类也会默认实现序列化
序列化对象时,static和transient修饰的成员不会被序列化
加载全部内容