Serialisierung
Motivation
public class Student {
private int id;
private String name;
private School school;
private Address address;
public Student(byte[]) { ... }
public byte[] serialize() { ... }
Implementierung
public byte[] serialize() throws IOException {
try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
DataOutputStream output = new DataOutputStream(baos)) {
output.writeInt(id);
output.writeUTF(name);
output.write(school.serialize());
output.write(address.serialize());
return baos.toByteArray();
}
}
public Student(byte[] data) throws IOException {
try (DataInputStream dis = new DataInputStream(
new ByteArrayInputStream(data))) {
id = dis.readInt();
name = dis.readUTF();
school = new School(dis.readNBytes(???));
address = new Address(dis.readNBytes(???));
}
}
ObjectOutputStream
School htl = new School("HTL");
Student student = new Student(42, "Bob", htl);
try (ObjectOutputStream output = new ObjectOutputStream(
new FileOutputStream("student.dat"))) {
output.writeObject(student);
}
Exception in thread "main" java.io.NotSerializableException:
serializing.domain.Student
Serializable
public interface Serializable { }
Marker-Interface, markiert Klasse als serialisierbar
public class Student implements Serializable
School htl = new School("HTL");
Student student = new Student(42, "Bob", htl);
try (ObjectOutputStream output = new ObjectOutputStream(
new FileOutputStream("student.dat"))) {
output.writeObject(student);
}
Exception in thread "main" java.io.NotSerializableException:
serializing.domain.School
public class School implements Serializable
School htl = new School("HTL");
Student student = new Student(42, "Bob", htl);
try (ObjectOutputStream output = new ObjectOutputStream(
new FileOutputStream("student.dat"))) {
output.writeObject(student);
}
try (ObjectInputStream input = new ObjectInputStream(
new FileInputStream("student.dat"))) {
Student deserialized = (Student) input.readObject();
}
Customization
transient
public class Student implements Serializable {
private int id;
private String name;
private transient List<Grade> grades;
...
}
Beim Serialisieren nicht berücksichtigt:
- statische Felder
- transiente Felder
writeObject/readObject
public class Student implements Serializable {
private int id;
private String name;
private School school;
@Serial
private void writeObject(ObjectOutputStream output)
throws IOException {
output.writeByte(42);
output.writeUTF("Chuck Norris");
}
@Serial
private void readObject(ObjectInputStream input)
throws IOException, ClassNotFoundException {
id = input.readByte();
name = input.readUTF();
}
}
School htl = new School("HTL");
Student student = new Student(17, "Bob", htl);
try (ObjectOutputStream output = new ObjectOutputStream(
new FileOutputStream("student.dat"))) {
output.writeObject(student);
}
try (ObjectInputStream input = new ObjectInputStream(
new FileInputStream("student.dat"))) {
Student deserialized = (Student) input.readObject();
}
Student{id=42, name='Chuck Norris', school=null}
komplette Kontrolle über Serialisierung
serialVersionUID
- Objekt wird serialisiert
- Klasse wird verändert
- Objekt wird deserialisiert
- ✔️ wenn
serialVersionUIDident - 💥 sonst
- ✔️ wenn
serialVersionUIDwird bei Bedarf vom Compiler automatisch generiert 👍
public class Student implements Serializable {
@Serial
private static final long serialVersionUID = 42L;
...