相关疑难解决方法(0)

如何序列化lambda?

我怎样才能优雅地序列化lambda?

例如,下面的代码抛出一个NotSerializableException.如何在不创建SerializableRunnable"虚拟"界面的情况下修复它?

public static void main(String[] args) throws Exception {
    File file = Files.createTempFile("lambda", "ser").toFile();
    try (ObjectOutput oo = new ObjectOutputStream(new FileOutputStream(file))) {
        Runnable r = () -> System.out.println("Can I be serialized?");
        oo.writeObject(r);
    }

    try (ObjectInput oi = new ObjectInputStream(new FileInputStream(file))) {
        Runnable  r = (Runnable) oi.readObject();
        r.run();
    }
}
Run Code Online (Sandbox Code Playgroud)

java lambda serialization java-8

152
推荐指数
4
解决办法
4万
查看次数

可以显式删除lambda的序列化支持

由于已经知道它很容易地添加序列化支持lambda表达式时,目标接口已经不继承Serializable,只是喜欢(TargetInterface&Serializable)()->{/*code*/}.

我问,是一种反其道而行之,明确删除支持串行当目标接口继承Serializable.

由于您无法从类型中删除接口,因此基于语言的解决方案可能看起来像(@NotSerializable TargetInterface)()->{/* code */}.但据我所知,没有这样的解决方案.(纠正我,如果我错了,这将是一个完美的答案)

即使在类实现时拒绝序列化是Serializable过去的合法行为,并且程序员控制下的类,模式看起来如下:

public class NotSupportingSerialization extends SerializableBaseClass {
    private void writeObject(java.io.ObjectOutputStream out) throws IOException {
      throw new NotSerializableException();
    }
    private void readObject(java.io.ObjectInputStream in)
      throws IOException, ClassNotFoundException {
      throw new NotSerializableException();
    }
    private void readObjectNoData() throws ObjectStreamException {
      throw new NotSerializableException();
    }
}
Run Code Online (Sandbox Code Playgroud)

但是对于lambda表达式,程序员没有对lambda类的控制.


为什么有人会费心去除支持?好吧,除了生成包含Serialization支持的更大代码之外,它还会产生安全风险.请考虑以下代码:

public class CreationSite {
    public static void main(String... arg) {
        TargetInterface f=CreationSite::privateMethod;
    } …
Run Code Online (Sandbox Code Playgroud)

java lambda serialization java-8

35
推荐指数
1
解决办法
2423
查看次数

如何使函数Serializable以通用方式

我知道我们可以将函数转换为Serializable需要它的位置.

但是,我想将此转换移动到通用方法,以使使用代码更简洁.我无法创建这样的方法.

我的具体问题是下面的地图不是Serializable:

final Map<MyObject, String> map =
        new TreeMap<>(Comparator.comparing(MyObject::getCode));
Run Code Online (Sandbox Code Playgroud)

我可以通过使用:

final Map<MyObject, String> map =
        new TreeMap<>(Comparator.comparing((Function<MyObject, String> & Serializable) MyObject::getCode));
Run Code Online (Sandbox Code Playgroud)

但我希望能够做到这样的事情:

final Map<MyObject, String> map =
        new TreeMap<>(Comparator.comparing(makeSerializable(MyObject::getCode)));

public static <T, U> Function<T, U> makeSerializable(Function<T, U> function) {
    return (Function<T, U> & Serializable) function;
}
Run Code Online (Sandbox Code Playgroud)

对于编译器这很好,但在运行时,我得到一个ClassCastException:

java.lang.ClassCastException: SerializableTest$$Lambda$1/801197928 cannot be cast to java.io.Serializable
Run Code Online (Sandbox Code Playgroud)

我也尝试了以下替代方案,但没有成功:

// ClassCastException
public static <T extends Serializable, U extends Serializable> Function<T, U> makeSerializable(Function<T, U> …
Run Code Online (Sandbox Code Playgroud)

java generics lambda comparator java-8

4
推荐指数
1
解决办法
592
查看次数

标签 统计

java ×3

java-8 ×3

lambda ×3

serialization ×2

comparator ×1

generics ×1