java - valores - Serialización y objetos inmutables.
objetos mutables e inmutables java (6)
En el caso típico de serialización, no se requiere que la clase tenga un constructor vacío o campos no finales para ser serializables.
Ahora, si tiene que hacer su propia serialización, o necesita subclasificar una clase que no implementa Serializable, esa es una historia diferente.
Por lo tanto, debe proporcionar más detalles sobre cómo está teniendo un problema.
Tengo una clase destinada a un uso inmutable, por lo que me gustaría etiquetar todos los campos como final
.
Sin embargo, la clase se serializa y se deserializa para enviarla a través de la red. Para que esto funcione se requiere un constructor vacío. Esto me impide crear los campos finales.
Estoy seguro de que este es un problema bastante común, pero no puedo encontrar una solución. ¿Cómo debo proceder?
Este problema es un error abierto en el lenguaje Java . (Tenga en cuenta que esto solo se aplica si tiene que realizar la serialización manualmente, como con readObject)
No se requiere un constructor sin argumentos. La clase no derivada en serie más derivada necesita un constructor sin argumentos disponible para la clase derivable más derivada.
Si necesita mutar los campos dentro de un readObject
, entonces use un proxy serial a través de readResolve
y writeReplace
.
No se requiere un constructor sin argumentos. Vamos a leer el código fuente:
// java.io.ObjectStreamClass
private static Constructor<?> getSerializableConstructor(Class<?> cl) {
Class<?> initCl = cl;
while (Serializable.class.isAssignableFrom(initCl)) {
if ((initCl = initCl.getSuperclass()) == null) {
return null;
}
}
...
}
Entonces, en realidad, el constructor no-arg es necesario en la clase más cercana no Serializable
en la jerarquía de tipos.
Significa que la siguiente clase de Domain
puede ser serializada.
class Domain implements Serializable {
private final int a;
public Domain(int a) {
this.a = a;
}
}
Pero la clase Son
no puede:
class Father{
private final int a;
public Father(int a) {
this.a = a;
}
}
class Son extends Father implements Serializable {
public Son(int a) {
super(a);
}
}
Para el registro, ya que tuve un problema similar:
Recibí un mensaje " java.io.InvalidClassException: com.example.stuff.FooBar; com.example.stuff.FooBar; ningún constructor válido "
Pensé que era porque faltaba un constructor por defecto. Pero las respuestas anteriores confirman que no es obligatorio (pero nuestra aplicación utiliza un serializador antiguo que de hecho requiere un constructor predeterminado, por lo que puede surgir el caso).
Entonces encontré una página que decía:
Si una clase que está diseñada para herencia no es serializable, puede ser imposible escribir una subclase serializable. Específicamente, será imposible si la superclase no proporciona un constructor sin parámetros accesible.
De ahí el mensaje que recibí, supongo. Parecía que el problema central era clásico: declaré una clase como serializable, ¡pero la superclase no! Moví la interfaz Serializable hacia arriba en la jerarquía, y todo estaba bien.
Pero el mensaje fue un poco engañoso ... :-)
Para repetir lo que se ha dicho, los constructores no-arg no son un requisito si está tomando la ruta de implementación de la interfaz java.io.Serializable
. Eche un vistazo al código fuente java.lang.Integer
, por ejemplo, una clase simple serializable / inmutable que tiene dos constructores: uno que toma un int, y otro que toma una cadena. Código fuente: http://www.docjar.com/html/api/java/lang/Integer.java.html . Javadoc: http://java.sun.com/javase/6/docs/api/java/lang/Integer.html .
También dependiendo de la complejidad de su clase y de lo que esté haciendo, podría considerar la implementación de la serialización a través de la interfaz java.io.Externalizable
(aunque algunos consideran que está desactualizada y SÍ requiere un constructor sin argumentos). Aquí hay una descripción general de SO: ¿Cuál es la diferencia entre Serializable y Externalizable en Java? , y aquí está el tutorial oficial de Java: http://java.sun.com/docs/books/tutorial/javabeans/persistence/index.html .