枚举类是可序列化的,因此用枚举序列化对象没有问题。另一种情况是类具有java.util.optional类的字段。在本例中,将引发以下异常:java.io.notserializableexception:java.util.optional
如何处理这些类,如何序列化它们?是否可以将这些对象发送到远程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);
}
}
}
6条答案
按热度按时间ajsxfq5m1#
这个答案是为了回答标题中的问题“optional不应该是可序列化的吗?”简单的回答是javalambda(jsr-335)Maven组考虑并拒绝了它。这一条和这一条表明
Optional
当返回值可能不存在时,将用作函数的返回值。其目的是让调用者立即检查Optional
并提取实际值(如果存在)。如果该值不存在,调用方可以替换默认值、抛出异常或应用其他策略。这通常是通过链接fluent方法调用返回的流管道(或其他方法)的末尾来完成的Optional
价值观。它从来不是为
Optional
以其他方式使用,例如用于可选方法参数或存储为对象中的字段。顺其自然地说Optional
可串行化将使它能够持久地存储或通过网络传输,这两者都鼓励使用远远超出其最初的设计目标。通常有更好的方法来组织数据,而不是存储数据
Optional
在田野里。如果一个吸气剂(如getValue
方法)返回实际值Optional
从字段开始,它强制每个调用者实现一些处理空值的策略。这可能会导致呼叫者之间的不一致行为。通常最好让该字段的任何代码集在设置时应用某些策略。有时人们想把
Optional
收藏,比如List<Optional<X>>
或者Map<Key,Optional<Value>>
. 这通常也是个坏主意。最好是把这些用法替换掉Optional
对象值为空(不是实际值null
引用),或者干脆从集合中完全忽略这些条目。mu0hgdu02#
如果你想要一个可序列化的可选的,可以考虑改用guava的可选的,它是可序列化的。
q3aa05253#
io库(以前的javaslang)也有
Option
可序列化的类:v7pvogib4#
很多
Serialization
相关的问题可以通过将持久化序列化表单与您操作的实际运行时实现解耦来解决。班级
Optional
实现允许在处理可能缺少的值时编写好代码的行为(与使用null
). 但它并没有给数据的持久表示带来任何好处。它只会让你的序列化数据更大…上面的草图看起来可能很复杂,但这是因为它只演示了一个属性的模式。你的类有越多的属性,它的简单性就应该被揭示出来。
而且不要忘了,改变执行的可能性
My
完全不需要调整持久形式…xxe27gdn5#
这是一个奇怪的遗漏。
你必须把这个字段标记为
transient
提供你自己的习惯writeObject()
编写get()
结果本身readObject()
恢复Optional
从流中读取结果。别忘了打电话defaultWriteObject()
以及defaultReadObject()
分别。iibxawm46#
如果您想维护一个更一致的类型列表并避免使用null,那么有一个奇怪的替代方法。
可以使用类型的交集存储值。再加上一个lambda,可以实现如下功能:
拥有
temp
变量separate避免关闭value
成员,因此序列化太多。