JDK序列化官方指南
在网络中数据传输都是以字节数组传输的,而在java程序中操作的是类对象。java程序中对象到对象的传递在网络中的传输过程为:
- 将对象序列化为字节数组发送到网络的接收方
- 网络接收方接收到字节数组反序列化为对象
java语言提供了一整套完成的序列化框架用于完成对象的序列化和反序列化
Special handling is required for arrays, enum constants, and objects of type Class, ObjectStreamClass, and String. Other objects must implement either the
Serializable
or theExternalizable
interface to be saved in or restored from a stream
除了数组,枚举类型,ObjectStreamClass
和String
类型,其他对象序列化必须实现Serializable
或Externalizable
接口
For a
Serializable
class, Object Serialization can automatically save and restore fields of each class of an object and automatically handle classes that evolve by adding fields or supertypes. A serializable class can declare which of its fields are saved or restored, and write and read optional values and objects.
For anExternalizable
class, Object Serialization delegates to the class complete control over its external format and how the state of the supertype(s) is saved and restored.
显示指定序列化字段
默认情况下,不使用transient
修饰的字段都是可以序列化的,也可以使用如下方式显示指定序列化字段
class List implements Serializable {
List next;
private static final ObjectStreamField[] serialPersistentFields
= {new ObjectStreamField("next", List.class)};
}
Serializable接口
序列化和无参构造函数的关系
- 单一对象,无继承关系:若想实现序列化与反序列化,则必须实现序列化接口,否则报异常:
NotSerializableException
- 对象间有继承关系,但无引用关系,若想实现序列化与反序列化,则父类必须实现序列化接口或提供无参构造函数,否则报
invalidClassException
- 对象间有继承关系,并且有引用关系,若想实现序列化与反序列化,则父类必须实现序列化接口
具体细节和demo可以参考这篇博客
https://blog.csdn.net/zh15732621679/article/details/79803105
方法
- private void writeObject 自定义序列化
- private void readObject 自定义反序列化
- writeReplace
- readResolve
Externalizable 接口
- writeExternal
- readExternal
- writeReplace
- readResolve
Writing to an Object Stream
序列化今天的日期到文件
FileOutputStream f = new FileOutputStream("tmp");
ObjectOutput s = new ObjectOutputStream(f);
s.writeObject("Today");
s.writeObject(new Date());
s.flush();
- 序列化对象使用
ObjectOutput
的writeObject
方法 - ObjectOutputStream can be extended to customize the information about classes in the stream or to replace objects to be serialized. Refer to the annotateClass and replaceObject method descriptions for details.
Reading from an Object Stream
从文件中反序列化出日期
FileInputStream in = new FileInputStream("tmp");
ObjectInputStream s = new ObjectInputStream(in);
String today = (String)s.readObject();
Date date = (Date)s.readObject();
- 序列化对象使用
ObjectInput
的readObject
方法 - ObjectInputStream can be extended to utilize customized information in the stream about classes or to replace objects that have been deserialized. Refer to the resolveClass and resolveObject method descriptions for details.
Documenting Serializable Fields and Data for a Class
序列化有关的java doc注解:
- @serial
- @serialField
- @serialData
demo
public class SerdeDemo {
static class User implements Serializable {
public User(String username, String password) {
this.username = username;
this.password = password;
}
private String username;
transient private String password;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
private void writeObject(ObjectOutputStream objectOutputStream) throws IOException {
objectOutputStream.defaultWriteObject();
objectOutputStream.writeObject(password);
}
private void readObject(ObjectInputStream objectInputStream) throws IOException, ClassNotFoundException {
objectInputStream.defaultReadObject();
password=(String)objectInputStream.readObject();
}
@Override
public String toString() {
return "User{" +
"username='" + username + '\'' +
", password='" + password + '\'' +
'}';
}
}
public static void main(String[] args) throws IOException, ClassNotFoundException {
User user=new User("xiaoming","ABC123");
ByteArrayOutputStream outputStream=new ByteArrayOutputStream();
ObjectOutputStream objectOutputStream=new ObjectOutputStream(outputStream);
objectOutputStream.writeObject(user);
InputStream inputStream=new ByteArrayInputStream(outputStream.toByteArray());
ObjectInputStream objectInputStream=new ObjectInputStream(inputStream);
User user1=(User)objectInputStream.readObject();
System.out.println(user1);
}
}
默认行为不会序列化transient
修饰的字段,可以通过writeObject,readObject
实现自定义的序列化
参考
https://docs.oracle.com/en/java/javase/13/docs/specs/serialization/index.html