La clase Enum es serializable, por lo que no hay ningún problema para serializar objetos con enumeraciones. El otro caso es donde la clase tiene campos de clase java.util.Optional. En este caso, se lanza la siguiente excepción: java.io.NotSerializableException: java.util.Optional
¿Cómo lidiar con tales clases, cómo serializarlas? ¿Es posible enviar tales objetos a Remote EJB oa través de RMI?
Este es el ejemplo:
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.Optional;
import org.junit.Test;
public class SerializationTest {
static class My implements Serializable {
private static final long serialVersionUID = 1L;
Optional<Integer> value = Optional.empty();
public void setValue(Integer i) {
this.i = Optional.of(i);
}
public Optional<Integer> getValue() {
return value;
}
}
//java.io.NotSerializableException is thrown
@Test
public void serialize() {
My my = new My();
byte[] bytes = toBytes(my);
}
public static <T extends Serializable> byte[] toBytes(T reportInfo) {
try (ByteArrayOutputStream bstream = new ByteArrayOutputStream()) {
try (ObjectOutputStream ostream = new ObjectOutputStream(bstream)) {
ostream.writeObject(reportInfo);
}
return bstream.toByteArray();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
java
serialization
java-8
optional
vanarchi
fuente
fuente
Optional
se marcó comoSerializable
, ¿qué pasaría si seget()
devolviera algo que no se puede serializar?NotSerializableException,
por supuesto.Respuestas:
Esta respuesta es en respuesta a la pregunta en el título, "¿No debería ser opcional serializable?" La respuesta corta es que el grupo de expertos Java Lambda (JSR-335) lo consideró y lo rechazó . Esa nota, y esta y esta, indican que el objetivo principal del diseño
Optional
es que se utilice como valor de retorno de funciones cuando un valor de retorno puede estar ausente. La intención es que la persona que llama verifique inmediatamenteOptional
y extraiga el valor real si está presente. Si el valor está ausente, la persona que llama puede sustituir un valor predeterminado, lanzar una excepción o aplicar alguna otra política. Por lo general, esto se hace encadenando llamadas de método fluidas al final de una canalización de flujo (u otros métodos) que devuelvenOptional
valores.Nunca fue pensado para
Optional
ser usado de otras formas, como para argumentos de métodos opcionales o para ser almacenado como un campo en un objeto . Y, por extensión, hacerOptional
serializable permitiría almacenarlo de forma persistente o transmitirlo a través de una red, lo que fomenta usos mucho más allá de su objetivo de diseño original.Por lo general, hay mejores formas de organizar los datos que almacenarlos
Optional
en un campo. Si un captador (como elgetValue
método de la pregunta) devuelve el valor realOptional
del campo, obliga a cada llamador a implementar alguna política para tratar con un valor vacío. Esto probablemente dará lugar a un comportamiento inconsistente entre las personas que llaman. A menudo es mejor que cualquier conjunto de códigos de ese campo aplique alguna política en el momento en que se establece.A veces la gente quiere poner
Optional
en colecciones, comoList<Optional<X>>
oMap<Key,Optional<Value>>
. Esto también suele ser una mala idea. A menudo es mejor reemplazar estos usos deOptional
con valores de objeto nulo (nonull
referencias reales ), o simplemente omitir estas entradas de la colección por completo.fuente
Se
Serialization
pueden resolver muchos problemas relacionados desacoplando la forma serializada persistente de la implementación real en tiempo de ejecución en la que opera.La clase
Optional
implementa un comportamiento que permite escribir un buen código cuando se trata de valores posiblemente ausentes (en comparación con el uso denull
). Pero no agrega ningún beneficio a una representación persistente de sus datos. Solo haría que sus datos serializados fueran más grandes ...El dibujo anterior puede parecer complicado, pero eso se debe a que muestra el patrón con una sola propiedad. Cuantas más propiedades tenga su clase, más se revelará su simplicidad.
Y no olvidar, la posibilidad de cambiar la implementación de
My
completamente sin necesidad de adaptar la forma persistente ...fuente
class My
, lo que normalmente se hace ya que también es útil para otros usos,readResolve
podría ser una implementación de una sola línea, reduciendo así el texto estándar a una sola línea por propiedad. Lo cual no es mucho dado el hecho de que cada propiedad mutable tiene al menos siete líneas de código en la clase deMy
todos modos.Si desea un opcional serializable, considere usar en su lugar el opcional de guava, que es serializable.
fuente
Es una omisión curiosa.
Tendría que marcar el campo como
transient
y proporcionar su propiowriteObject()
método personalizado que escribió elget()
resultado en sí, y unreadObject()
método que restauró alOptional
leer ese resultado de la secuencia. Sin olvidar llamardefaultWriteObject()
ydefaultReadObject()
respectivamente.fuente
La biblioteca Vavr.io (antes Javaslang) también tiene la
Option
clase que es serializable:fuente
Si desea mantener una lista de tipos más consistente y evitar el uso de null, hay una alternativa chiflada.
Puede almacenar el valor utilizando una intersección de tipos . Junto con una lambda, esto permite algo como:
Tener la
temp
variable separada evita cerrar sobre el propietario delvalue
miembro y, por lo tanto, serializar demasiado.fuente