van*_*chi 101 java serialization optional java-8
Enum类是Serializable,因此使用枚举序列化对象没有问题.另一种情况是class具有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);
}
}
}
Run Code Online (Sandbox Code Playgroud)
Stu*_*rks 154
这个答案是对标题中的问题的回答:"不应该是可序列化的吗?" 简短的回答是Java Lambda(JSR-335)专家组考虑并拒绝了它.那个注释,这一个和这一个表明,Optional
当返回值可能不存在时,主要的设计目标是用作函数的返回值.目的是调用者立即检查Optional
并提取实际值(如果存在).如果该值不存在,则调用者可以替换默认值,抛出异常或应用其他一些策略.这通常通过在返回Optional
值的流管道(或其他方法)的末尾链接流式方法调用来完成.
它从未打算Optional
用于其他方式,例如可选方法参数或作为字段存储在对象中.通过扩展,使Optional
序列化可以使其能够持久存储或通过网络传输,这两者都鼓励使用远远超出其原始设计目标.
通常,有更好的方法来组织数据,而不是存储Optional
在字段中.如果getter(例如问题中的getValue
方法)Optional
从字段返回实际值,它会强制每个调用者实现一些处理空值的策略.这可能会导致呼叫者之间出现不一致的行为.拥有该字段在设置时应用某些策略的任何代码集通常会更好.
有时人们想要Optional
收藏,比如List<Optional<X>>
或Map<Key,Optional<Value>>
.这也是一个坏主意.通常最好以取代这些用法Optional
与空-对象的值(不是实际null
的参考),或者干脆完全忽略从收集这些条目.
Hol*_*ger 15
Serialization
通过将持久化序列化形式与您操作的实际运行时实现分离,可以解决许多相关问题.
/** 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;
}
}
Run Code Online (Sandbox Code Playgroud)
该类Optional
实现的行为允许在处理可能缺少的值时编写好的代码(与使用相比null
).但它不会为数据的持久表示添加任何好处.它只会使您的序列化数据更大......
上面的草图可能看起来很复杂,但这是因为它仅使用一个属性演示模式.你的班级拥有的属性越多,它的简洁性就越多.
而且不要忘记,My
完全改变执行的可能性,而不需要调整持久形式......
Vavr.io 库(以前的 Javaslang)也有Option
可序列化的类:
public interface Option<T> extends Value<T>, Serializable { ... }
Run Code Online (Sandbox Code Playgroud)