A classe Enum é Serializable, portanto, não há problema em serializar o objeto com enums. O outro caso é onde a classe possui campos da classe java.util.Optional. Nesse caso, a seguinte exceção é lançada: java.io.NotSerializableException: java.util.Optional
Como lidar com essas classes, como serializá-las? É possível enviar tais objetos para EJB Remoto ou por RMI?
Este é o exemplo:
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
fonte
fonte
Optional
foi marcado comoSerializable
, o que aconteceria seget()
retornasse algo que não fosse serializável?NotSerializableException,
claro.Respostas:
Essa resposta é uma resposta à pergunta do título, "O opcional não deve ser serializável?" A resposta curta é que o grupo de especialistas Java Lambda (JSR-335) considerou e rejeitou . Essa nota, e esta e esta indicam que o objetivo principal do projeto
Optional
é ser usado como o valor de retorno de funções quando um valor de retorno pode estar ausente. A intenção é que o chamador verifique imediatamenteOptional
e extraia o valor real, se estiver presente. Se o valor estiver ausente, o chamador pode substituir um valor padrão, lançar uma exceção ou aplicar alguma outra política. Isso normalmente é feito encadeando chamadas de método fluentes no final de um pipeline de fluxo (ou outros métodos) que retornamOptional
valores.Nunca foi planejado para
Optional
ser usado de outras maneiras, como para argumentos de método opcionais ou para ser armazenado como um campo em um objeto . E, por extensão, tornarOptional
serializável permitiria que ele fosse armazenado de forma persistente ou transmitido através de uma rede, o que encoraja usos muito além de seu objetivo de design original.Normalmente, existem maneiras melhores de organizar os dados do que armazenar um
Optional
em um campo. Se um getter (como ogetValue
método em questão) retorna o valor realOptional
do campo, ele força cada chamador a implementar alguma política para lidar com um valor vazio. Isso provavelmente levará a um comportamento inconsisente entre os chamadores. Geralmente, é melhor fazer com que os conjuntos de códigos desse campo apliquem alguma política no momento em que são definidos.Às vezes, as pessoas querem colocar
Optional
em coleções, comoList<Optional<X>>
ouMap<Key,Optional<Value>>
. Geralmente, isso também é uma má ideia. Muitas vezes é melhor substituir esses usos deOptional
por valores de Objeto Nulo (não reaisnull
referências ) ou simplesmente omitir totalmente essas entradas da coleção.fonte
Muitos
Serialization
problemas relacionados podem ser resolvidos desacoplando o formulário serializado persistente da implementação de tempo de execução real em que você opera.A classe
Optional
implementa um comportamento que permite escrever um bom código ao lidar com valores possivelmente ausentes (em comparação com o uso denull
). Mas isso não adiciona nenhum benefício a uma representação persistente de seus dados. Isso apenas aumentaria seus dados serializados ...O esboço acima pode parecer complicado, mas isso porque demonstra o padrão com apenas uma propriedade. Quanto mais propriedades sua classe tiver, mais sua simplicidade deve ser revelada.
E não se esqueça, a possibilidade de alterar a implementação de
My
completamente sem qualquer necessidade de adaptar a forma persistente…fonte
class My
, o que você geralmente faz porque é útil para outros usos também,readResolve
poderia ser uma implementação de linha única, reduzindo assim o clichê a uma única linha por propriedade. O que não é muito, dado o fato de que cada propriedade mutável tem pelo menos sete linhas de código na classeMy
.Se você quiser um opcional serializável, considere usar o opcional do guava, que é serializável.
fonte
É uma omissão curiosa.
Você teria que marcar o campo como
transient
e fornecer seu própriowriteObject()
método customizado que escreveu oget()
próprio resultado e umreadObject()
método que restaurou oOptional
ao ler esse resultado do fluxo. Não esquecendo de ligardefaultWriteObject()
edefaultReadObject()
respectivamente.fonte
A biblioteca Vavr.io (antigo Javaslang) também tem a
Option
classe que é serializável:fonte
Se você deseja manter uma lista de tipos mais consistente e evitar o uso de null, há uma alternativa estranha.
Você pode armazenar o valor usando uma interseção de tipos . Juntamente com um lambda, isso permite algo como:
Ter a
temp
variável separada evita fechar sobre o proprietário dovalue
membro e, portanto, serializar demais.fonte