java - lambda的序列化和反序列化

标签 java java-8

下面的代码抛出

Exception in thread "main" java.lang.ClassCastException: test.Subclass2 cannot be cast to test.Subclass1
at test.LambdaTest.main(LambdaTest.java:17)

public class LambdaTest {

    public static void main(String[] args) throws IOException, ClassNotFoundException {
        ToLongFunction<B> fn1 = serde((ToLongFunction<B> & Serializable) B::value);
        ToLongFunction<C> fn2 = serde((ToLongFunction<C> & Serializable) C::value);
        fn1.applyAsLong(new B());
        fn2.applyAsLong(new C()); // Line 17 -- exception here!
    }

    private static <T extends Serializable> T serde(T t) throws IOException, ClassNotFoundException {
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        new ObjectOutputStream(bos).writeObject(t);
        ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bos
                .toByteArray()));
        return (T) ois.readObject();
    }
}

class A {
    public long value() {
        return 0;
    }
}

class B extends A { }

class C extends A { }

原因好像是经过序列化和反序列化之后,fn1和fn2最终都是同一个类。这是 JDK/编译器错误还是我遗漏了有关 lambda 序列化和反序列化的内容?

最佳答案

看看 2016 年提出的这个 Open JDK 问题:

Deserialization of lambda causes ClassCastException

它非常符合您的场景:

  • Two (distinct) classes, B and C, both of which extend the same base class, A, which has a method, String f().
  • Create a Supplier reference to method f() for an object of type B; call this bf [new B()::f].
  • Create a Supplier reference to method f() for an object of type C; cal this cf [new C()::f].
  • Serialize cf (ObjectOutputStream#writeObject)
  • When the serialized cf is deserialized (ObjectInputStream#readObject), a ClassCastException is thrown saying that class C cannot be cast to class B

关于这个问题有一个有趣的讨论,但 Dan Smith 的最后评论似乎一语中的:

Important observation for this particular test case: the "qualifying type" (i.e., the class named by the bytecode) of a method reference should be the same as the qualifying type of an invocation: the type of the receiver. javac is wrong to be using the type of the declaring class. See JDK-8059632.

Fix that bug, and I think the issue with different captured types goes away.

关于java - lambda的序列化和反序列化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48840989/

相关文章:

java - Int 流和收集

Java8 lambda 谓词异常

java - 短信接收表格

java - 具有复合模式的 Spring 中的循环引用

java - Java 8 Streams 是否与 .Net IEnumerable 相同?

java - 数组无法解析?这是构建路径问题吗?

使用来自 jni 的 openGL ES 时的 java glSurfaceView 与 Native-Activity

java - 无法启动 Activity - ComponentInfo 错误

java - 如何在 Java 中跨类共享变量,我试过 static 没有用

java - 作者使用 thenCompose 而不是 thenComposeAsync 的原因是否正确