Serialización personalizada: writeObject y readObject
Sobrescriba writeObject y readObject para implementar cifrado, compresión o una gestión personalizada de campos.
Serialización personalizada: writeObject y readObject es una lección gratuita de Java Academy en CoddyKit. Esta es la lección 3 de 4. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de Java Academy, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de Java Academy incluye 4 lecciones en total.
Cuando la serialización predeterminada no es suficiente
La serialización predeterminada guarda tal cual todos los campos que no son transient. A veces necesita cifrado, compresión o una representación diferente. Para eso existen los hooks writeObject / readObject.
Declaración de writeObject
Añada un método private void writeObject(ObjectOutputStream oos). Java lo llama en lugar del mecanismo predeterminado. Usted controla exactamente qué se escribe.
private void writeObject(ObjectOutputStream oos) throws IOException {
oos.defaultWriteObject(); // write non-transient fields normally
oos.writeUTF(encrypt(this.secret)); // write encrypted secret
}Declaración de readObject
Añada un método private void readObject(ObjectInputStream ois). Java lo llama durante la deserialización. Debe leer los datos exactamente en el mismo orden en que los escribió.
private void readObject(ObjectInputStream ois)
throws IOException, ClassNotFoundException {
ois.defaultReadObject(); // restore non-transient fields
this.secret = decrypt(ois.readUTF()); // decrypt and restore
}El orden es importante
Todo lo que escriba en writeObject debe leerse de nuevo en el mismo orden en readObject. Un orden diferente provoca StreamCorruptedException.
private void writeObject(ObjectOutputStream oos) throws IOException {
oos.writeInt(version);
oos.writeUTF(data);
}
private void readObject(ObjectInputStream ois)
throws IOException, ClassNotFoundException {
this.version = ois.readInt(); // same order
this.data = ois.readUTF();
}Compresión de datos durante la serialización
Envuelva el flujo con GZIPOutputStream dentro de writeObject para comprimir campos grandes y, después, use GZIPInputStream dentro de readObject para descomprimirlos.
private void writeObject(ObjectOutputStream oos) throws IOException {
oos.defaultWriteObject();
ByteArrayOutputStream bos = new ByteArrayOutputStream();
try (GZIPOutputStream gz = new GZIPOutputStream(bos)) {
gz.write(largePayload.getBytes());
}
oos.writeObject(bos.toByteArray());
}El hook readResolve
readResolve() se llama después de la deserialización. Devuelve un objeto de reemplazo; resulta útil para singletons y enums, ya que garantiza que solo exista una instancia después de la deserialización.
public class AppConfig implements Serializable {
private static final AppConfig INSTANCE = new AppConfig();
private AppConfig() {}
public static AppConfig getInstance() { return INSTANCE; }
private Object readResolve() { return INSTANCE; } // return singleton
}El hook writeReplace
writeReplace() se llama antes de la serialización. Devuelve otro objeto para serializarlo en su lugar; resulta útil para patrones de proxy y sustitutos de serialización.
private Object writeReplace() {
return new UserProxy(this.id); // serialize a lightweight proxy
}Validación de campos en readObject
Puede añadir lógica de validación dentro de readObject para rechazar datos no válidos o manipulados como parte de una estrategia de defensa en profundidad.
private void readObject(ObjectInputStream ois)
throws IOException, ClassNotFoundException {
ois.defaultReadObject();
if (age < 0 || age > 150) {
throw new InvalidObjectException("Invalid age: " + age);
}
}Gestión de cambios de versión
Use un campo de versión en writeObject para que readObject pueda gestionar correctamente los formatos antiguos y nuevos durante las migraciones.
private static final int SERIAL_VERSION = 2;
private void writeObject(ObjectOutputStream oos) throws IOException {
oos.defaultWriteObject();
oos.writeInt(SERIAL_VERSION);
if (SERIAL_VERSION >= 2) oos.writeUTF(email); // new field
}
private void readObject(ObjectInputStream ois)
throws IOException, ClassNotFoundException {
ois.defaultReadObject();
int v = ois.readInt();
if (v >= 2) this.email = ois.readUTF();
}Patrón de proxy de serialización
Un enfoque sólido consiste en escribir una clase interna estática privada que capture el estado mínimo y, después, usar writeReplace para escribir el proxy y su readResolve para reconstruir el objeto original.
Consideraciones de rendimiento
La serialización personalizada añade la sobrecarga de las llamadas a métodos, pero puede reducir considerablemente el tamaño de la carga útil. Realice pruebas de rendimiento antes de optimizar; use Externalizable para obtener el máximo control.
Comprobación rápida
¿Qué debe cumplirse con respecto al orden en writeObject y readObject?
Repaso
Personalice writeObject / readObject para cifrado, compresión o formatos personalizados. Use readResolve para singletons. Lea siempre en el mismo orden en que escribe.
Preguntas frecuentes
¿La lección «Serialización personalizada: writeObject y readObject» es gratis?
Sí — el texto completo de «Serialización personalizada: writeObject y readObject» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de Java Academy, actualiza a CoddyKit PRO. El curso de Java Academy incluye 4 lecciones en total.
¿Qué aprenderé en «Serialización personalizada: writeObject y readObject»?
Sobrescriba writeObject y readObject para implementar cifrado, compresión o una gestión personalizada de campos. Practicas Java Academy con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.
¿Necesito experiencia previa para empezar Java Academy?
No se requiere experiencia previa. Java Academy en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 3 de 4.
¿Cuánto tiempo toma la lección «Serialización personalizada: writeObject y readObject»?
La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.
¿Puedo escribir y ejecutar código en esta lección de Java Academy?
Sí. Cada lección de Java Academy incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.
Todas las lecciones de este curso
- Fundamentos de la serialización en Java
- Campos transient y serialVersionUID
- Serialización personalizada: writeObject y readObject
- Alternativas modernas: JSON y Protocol Buffers