在Java中, Serialization
意味着将对象转换为字节流,可以将其保存到文件中或通过网络传输, Deserialization
则相反。
序列化示例。
// Save object into a file.
public static void writeObject(Object obj, File file) throws IOException {
try (FileOutputStream fos = new FileOutputStream(file);
ObjectOutputStream oos = new ObjectOutputStream(fos)) {
oos.writeObject(obj);
oos.flush();
}
}
反序列化示例。
// Get object from a file.
public static Object readObject(File file) throws IOException, ClassNotFoundException {
Object result = null;
try (FileInputStream fis = new FileInputStream(file);
ObjectInputStream ois = new ObjectInputStream(fis)) {
result = ois.readObject();
}
return result;
}
1. POJO
查看一个简单的Person
类,实现Serializable
。
Person.java
package com.mkyong.io.object;
import java.io.Serializable;
import java.math.BigDecimal;
public class Person implements Serializable {
// optional, if missing, JVM will create it.
// better declare as a version control.
private static final long serialVersionUID = 1L;
private String name;
private int age;
// dun save this field into file
private transient BigDecimal salary;
// getters, setters, toString, constructor
}
在Java中,需要序列化的对象必须实现Serializable
接口,否则会遇到以下错误。
Terminal
Exception in thread "main" java.io.NotSerializableException: com.mkyong.io.object.Person
at java.base/java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1185)
at java.base/java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:349)
at com.mkyong.io.object.ObjectUtils.writeObject(ObjectUtils.java:14)
at com.mkyong.io.object.ObjectUtils.main(ObjectUtils.java:35)
2. Java序列化示例
参见注释以进行自我解释。
ObjectUtils.java
package com.mkyong.io.object;
import java.io.*;
import java.math.BigDecimal;
// serialization and deserialization
public class ObjectUtils {
// Serialization
// Save object into a file.
public static void writeObject(Person obj, File file) throws IOException {
try (FileOutputStream fos = new FileOutputStream(file);
ObjectOutputStream oos = new ObjectOutputStream(fos)) {
oos.writeObject(obj);
oos.flush();
}
}
// Deserialization
// Get object from a file.
public static Person readObject(File file) throws IOException, ClassNotFoundException {
Person result = null;
try (FileInputStream fis = new FileInputStream(file);
ObjectInputStream ois = new ObjectInputStream(fis)) {
result = (Person) ois.readObject();
}
return result;
}
public static void main(String[] args) throws IOException, ClassNotFoundException {
Person person = new Person("mkyong", 40, new BigDecimal(900));
// object -> file
ObjectUtils.writeObject(person, new File("person.obj"));
// file to object
Person obj = ObjectUtils.readObject(new File("person.obj"));
System.out.println(obj);
}
}
输出量
Terminal
Person{name='mkyong', age=40, salary=null}
什么是瞬态?
为什么薪水为零? 序列化期间,JVM会忽略所有transient
字段。 如果我们需要在序列化期间排除特定对象的字段,请将其标记为transient.
3.什么是serialVersionUID?
如果缺少serialVersionUID
,则JVM将自动创建它。 serialVersionUID
类似于版本号。 简而言之,如果我们将对象保存为1L
,则需要提供相同的1L
来读取对象,否则会遇到不兼容的错误。
Person.java
public class Person implements Serializable {
private static final long serialVersionUID = 1L;
//...
}
例如,我们将serialVersionUID = 1L
的对象保存到文件名person.obj
。 稍后,我们从对象中添加或删除一些字段,并将serialVersionUID
更新为2L
。 现在,读取person.obj
文件并尝试将其转换回修改后的对象,因为两个serialVersionUID
不同,我们将遇到以下不兼容错误:
Terminal
Exception in thread "main" java.io.InvalidClassException: com.mkyong.io.object.Person;
local class incompatible: stream classdesc serialVersionUID = 1, local class serialVersionUID = 2
at java.base/java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:689)
at java.base/java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1903)
at java.base/java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1772)
at java.base/java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2060)
at java.base/java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1594)
at java.base/java.io.ObjectInputStream.readObject(ObjectInputStream.java:430)
at com.mkyong.io.object.ObjectUtils.readObject(ObjectUtils.java:25)
at com.mkyong.io.object.ObjectUtils.main(ObjectUtils.java:38)
下载源代码
$ git clone https://github.com/mkyong/core-java.git
$ cd java-io
参考文献
- Java对象序列化规范
- 可序列化的JavaDoc
- ObjectInputStream JavaDoc
- ObjectOutputStreamJavaDoc
- Java –什么是serialVersionUID