EN
Java FIX for java.io.Not Serializable Exception: java.util.Optional
13
points
1. Problem description
How to solve java util Optional serializable exception?
Full stack trace:
Exception in thread "main" java.io.NotSerializableException: java.util.Optional
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1184)
at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1548)
at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1509)
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1432)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1178)
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:348)
Here is my code which explains what I've tried so far
Below code tries to serialize field Optional age
As the result we get:
Exception in thread "main" java.io.NotSerializableException: java.util.Optional
My code to get this exception:
import java.io.ByteArrayOutputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.Optional;
public class JavaUtilOptionalNotSerializableException {
private static class Foo implements Serializable {
private static final long serialVersionUID = 1L;
private final String name;
private final Optional<Integer> age;
private Foo(String name, Integer age) {
this.name = name;
this.age = Optional.ofNullable(age);
}
public String getName() {
return name;
}
public Optional<Integer> getAge() {
return age;
}
}
public static void main(String[] args) throws Exception {
/*
Exception in thread "main" java.io.NotSerializableException:
java.util.Optional
*/
tryToSerialize();
}
private static void tryToSerialize() throws Exception {
Foo foo = new Foo("123", 456);
byte[] arr;
try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos)) {
oos.writeObject(foo);
arr = baos.toByteArray();
}
assert arr != null;
}
}
2. Solution with java Optional
Solution no 1 to this problem is just do not use optional as field value
Instead use it as return type from the getter method
eg:
private final Integer age; // diff1: without Optional
public Optional<Integer> getAge() {
// diff2: each method invocation return new Optional
return Optional.ofNullable(age);
}
Entire code which solves your problem:
import java.io.ByteArrayOutputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.Optional;
public class JavaUtilOptionalSolution {
private static class Foo implements Serializable {
private static final long serialVersionUID = 1L;
private final String name;
private final Integer age; // diff1: without Optional
private Foo(String name, Integer age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public Optional<Integer> getAge() {
// diff2: each method invocation return new Optional
return Optional.ofNullable(age);
}
}
public static void main(String[] args) throws Exception {
// serialization works
tryToSerialize();
}
private static void tryToSerialize() throws Exception {
Foo foo = new Foo("123", 456);
byte[] arr;
try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos)) {
oos.writeObject(foo);
arr = baos.toByteArray();
}
assert arr != null;
}
}
3. Solution with Guava - Serializable Optional
Guava internally
// com.google.common.base.Optional
public abstract class Optional implements Serializable {
// ..
}