Enum 类是可序列化的,因此用枚举序列化对象没有问题。另一种情况是类具有 java.util.Optional 类的字段。在这种情况下会抛出以下异常:java.io.NotSerializableException: java.util.Optional
如何处理这样的类,如何序列化它们?是否可以将此类对象发送到 Remote EJB 或通过 RMI?
这是例子:
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);
}
}
}
原文由 vanarchi 发布,翻译遵循 CC BY-SA 4.0 许可协议
这个答案是对标题“Shouldn’t Optional be Serializable?”中的问题的回应。简短的回答是 Java Lambda (JSR-335) 专家组 考虑并拒绝了它。那个注释, 这个 和 这个 表明
Optional
的主要设计目标是在可能没有返回值时用作函数的返回值。目的是调用者立即检查Optional
并提取实际值(如果存在)。如果该值不存在,调用者可以替换默认值、抛出异常或应用其他一些策略。这通常是通过将流式方法调用链接到返回Optional
值的流管道(或其他方法)的末尾来完成的。它从未打算用于
Optional
以其他方式使用,例如用于 可选方法参数 或 作为字段存储在对象 中。通过扩展,使Optional
可序列化将使它能够持久存储或通过网络传输,这两者都鼓励使用远远超出其原始设计目标。通常有比在字段中存储
Optional
更好的方法来组织数据。如果 getter(例如问题中的getValue
方法)从字段中返回实际的Optional
,它会强制每个调用者实施一些处理空值的策略。这可能会导致呼叫者之间的行为不一致。通常最好让该字段在设置时应用某些策略的任何代码集。有时人们想将
Optional
放入集合中,例如List<Optional<X>>
或Map<Key,Optional<Value>>
。这通常也是一个坏主意。通常最好将Optional
的这些用法替换为 空对象 值(不是实际的null
引用),或者只是从集合中完全省略这些条目。