Why java.util.Optional is not Serializable, how to serialize an object with such fields

The Enum class is Serializable, so there is no problem serializing an object with enumerations. In another case, the class has fields java.util.Optional class. In this case, the following exception is thrown: java.io.NotSerializableException: java.util.Optional

How to deal with such classes, how to serialize them? Can I send such objects to Remote EJB or via RMI?

That's an example:

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); } } } 
+87
java java-8 serialization optional
Jul 03 '14 at 7:34
source share
6 answers

This answer answers the question in the headline: "Should I not be optionally Serializable?" The short answer is that the Java Lambda expert group (JSR-335) reviewed and rejected it . This note, this one and this one, indicates that the main design goal for Optional should be used as the return value of functions when the return value may be absent. The goal is for the caller to immediately check Optional and retrieve the actual value, if present. If there is no value, the caller can replace the default value, throw an exception, or apply another policy. This is usually done by chaining fluent method calls from the end of the stream pipeline (or other methods) that return Optional values.

It was never intended to be used by Optional other ways, for example, for optional method arguments or for being stored as a field in an object . And, by extension, the creation of Optional serializable would allow it to be permanently stored or transmitted over the network, both of which encourage use far beyond their original design goals.

There are usually better ways to organize data than storing Optional in a field. If the recipient (for example, the getValue method in the question) returns the actual Optional from the field, it forces each caller to implement some policy for working with an empty value. This is likely to lead to inconsistent behavior among subscribers. It is often better that the sets of codes used in the field apply a certain policy at the time of its installation.

Sometimes people want to put Optional in collections, such as List<Optional<X>> or Map<Key,Optional<Value>> . This is also usually a bad idea. It is often better to replace these Optional usages with Null-Object (not relevant null references) or simply omit these entries from the collection completely.

+133
Jul 03 '14 at 23:19
source share

Many of the problems associated with Serialization can be solved by decoupling the persistent serialized form from the actual implementation in which you work.

 /** The class you work with in your runtime */ public class My implements Serializable { private static final long serialVersionUID = 1L; Optional<Integer> value = Optional.empty(); public void setValue(Integer i) { this.value = Optional.ofNullable(i); } public Optional<Integer> getValue() { return value; } private Object writeReplace() throws ObjectStreamException { return new MySerialized(this); } } /** The persistent representation which exists in bytestreams only */ final class MySerialized implements Serializable { private final Integer value; MySerialized(My my) { value=my.getValue().orElse(null); } private Object readResolve() throws ObjectStreamException { My my=new My(); my.setValue(value); return my; } } 

The Optional class implements behavior that allows you to write good code when dealing with possibly missing values ​​(compared to using null ). But this does not add any benefit to the constant presentation of your data. It will just make your serialized data bigger ...

The sketch above may look complicated, but this is because it demonstrates a template with only one property. The more properties of your class, the more its simplicity should be disclosed.

And don't forget, the ability to completely change My implementation without the need to adapt a constant form ...

+12
Jul 03 '14 at 16:53
source share

If you want a serializable optional, consider instead a guava optional that you can serialize.

+7
Sep 22 '16 at 11:27
source share

This is a curious omission.

You would need to mark this field as transient and provide your own writeObject() method, which wrote the result of get() , and the readObject() method, which restored Optional by reading this result from the stream. Remember to call defaultWriteObject() and defaultReadObject() respectively.

+3
Jul 03 '14 at 7:42 on
source share

The Vavr.io library (formerly Javaslang) also has an Option class that can be serialized:

 public interface Option<T> extends Value<T>, Serializable { ... } 
0
Aug 27 '18 at 10:00
source share

If you want to maintain a more consistent type list and avoid using null, there is one weird alternative.

You can save the value using type intersection . In combination with lambda, this allows something like:

 private final Supplier<Optional<Integer>> suppValue; .... List<Integer> temp = value .map(v -> v.map(Arrays::asList).orElseGet(ArrayList::new)) .orElse(null); this.suppValue = (Supplier<Optional<Integer>> & Serializable)() -> temp==null ? Optional.empty() : temp.stream().findFirst(); 

temp variable temp separately, you can avoid closing the owner of value and, therefore, serialize too much.

0
Jan 30 '19 at 17:20
source share



All Articles