虽然可以在Java 8中序列化lambda,但强烈建议不要这样做;甚至不鼓励序列化内部类。给出的原因是lambdas可能无法在另一个JRE上正确反序列化。然而,这是否意味着有一种方法可以安全地序列化lambda?
例如,假设我定义一个类如下:
public class MyClass {
private String value;
private Predicate<String> validateValue;
public MyClass(String value, Predicate<String> validate) {
this.value = value;
this.validateValue = validate;
}
public void setValue(String value) {
if (!validateValue(value)) throw new IllegalArgumentException();
this.value = value;
}
public void setValidation(Predicate<String> validate) {
this.validateValue = validate;
}
}
如果像这样声明了类的实例,则不应序列化它:
MyClass obj = new MyClass("some value", (s) -> !s.isEmpty());
但如果我创建一个这样的类实例,会怎么样:
// Could even be a static nested class
public class IsNonEmpty implements Predicate<String>, Serializable {
@Override
public boolean test(String s) {
return !s.isEmpty();
}
}
MyClass isThisSafeToSerialize = new MyClass("some string", new IsNonEmpty());
现在序列化是安全的吗?我的直觉告诉我,是的,它应该是安全的,因为没有理由将java.util.function
中的接口与任何其他随机接口区别对待。但是我仍然很警惕。
这取决于您想要哪种安全性。序列化lambda并不是不能在不同JRE之间共享的情况。它们有一个定义良好的持久表示,即SerializedLambda
。当您研究它是如何工作的时,您会发现它依赖于定义类的存在,它将有一个特殊的方法来重建lambda。
使其不可靠的是对编译器特定工件的依赖,例如合成目标方法,它有一些生成的名称,因此插入另一个lambda表达式或使用不同的编译器重新编译类等简单更改可能会破坏与现有序列化lambda表达式的兼容性。
然而,使用手动编写的类并不能避免这种情况。如果没有显式声明的serialVersionUID,默认算法将通过散列类工件(包括私有工件和合成工件)来计算id,并添加类似的编译器依赖项。因此,如果想要可靠的持久化表单,最起码要声明一个显式的serialVersionUID。
或者你转向最健壮的形式:
public enum IsNonEmpty implements Predicate<String> {
INSTANCE;
@Override
public boolean test(String s) {
return !s.isEmpty();
}
}
序列化此常量不存储实际实现的任何属性,除了它的类名(当然还有它是枚举
的事实)和对常量名称的引用。反序列化后,将使用该名称的实际唯一实例。
请注意,可序列化的lambda表达式可能会产生安全问题,因为它们提供了另一种方法来获得允许调用目标方法的对象。然而,这适用于所有可序列化的类,因为问题和答案中显示的所有变量都允许故意反序列化对象,从而允许调用封装的操作。但对于显式可序列化类,作者通常更清楚这一事实。
问题内容: 我已经奋斗了几个小时,没有取得好结果。我正在尝试使用.NET JSON序列化程序将JSON从UI来回转换为对象。 小数引起了问题,因为我的文化的标准使用“,”作为小数分隔符而不是“。”。我尝试实现自定义转换器,但效果不佳。 我还检查了NewtonSoft JSON.net,但没有得到更好的结果。到目前为止,似乎与值类型的匹配是文化不变的。我要覆盖此行为,该怎么办? 顺便说一句,我真的很
问题内容: 我的直觉告诉我,必须以某种方式将其转换为字符串或byte [](在Go中甚至可能是相同的东西?),然后将其保存到磁盘。 我找到了这个包(http://golang.org/pkg/encoding/gob/),但似乎仅用于结构? 问题答案: 序列化数据有多种方法,Go为此提供了许多软件包。某些常见编码方式的软件包: 处理地图很好。以下示例显示了地图的编码/解码: 操场
问题内容: 我有一个Serializable对象,该对象应该将java.awt.Image作为其成员。我应该如何进行序列化? (抱歉,此版本是根据不太清晰的第一版编辑的。) 问题答案: ImageIcon实现了Serializable,可用于包装Image类 http://java.sun.com/j2se/1.5.0/docs/api/javax/swing/ImageIcon.html
文档中说
从捆绑包反序列化LinkedHashMaps的正确方法是什么?完全可以做到吗?如果不是,我如何保持顺序而不在中间添加另一层来跟踪位置,这将涉及更改大量现有代码?
问题内容: 我想使用GSON将下面的Example类序列化为JSON。 我期望得到以下输出: 但是调用函数返回 看来GSON无法在Map 内序列化Map 。这是GSON的限制,还是我在这里做错了? 问题答案: Nishant的答案之所以起作用,是因为Gson的默认构造函数默认启用了所有东西,否则您将不得不使用GsonBuilder手动启用它们。 从JavaDocs: 使用默认配置构造一个Gson对