以下代码抛出
Exception in thread "main" java.lang.ClassCastException: test.Subclass2 cannot be cast to test.Subclass1
at test.LambdaTest.main(LambdaTest.java:17)
Run Code Online (Sandbox Code Playgroud)
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 { }
Run Code Online (Sandbox Code Playgroud)
原因似乎是在序列化和反序列化之后,fn1和fn2都以同一个类结束.这是一个JDK /编译器错误还是我错过了关于lambdas的序列化和反序列化的一些内容?
看看2016年提出的Open JDK问题:
lambda的反序列化导致ClassCastException
它非常精确地匹配您的场景:
- 两个(不同的)类,
B并且C都扩展了相同的基类A,它有一个方法,String f().- 为类型对象创建
Supplier方法的引用; 叫这个[ ].f()Bbfnew B()::f- 为类型对象创建
Supplier方法的引用; cal this [ ].f()Ccfnew C()::f- 序列化
cf(ObjectOutputStream#writeObject)- 当序列化
cf被反序列化(ObjectInputStream#readObject)时,ClassCastException抛出一个说C不能将类强制转换为类B
关于这个问题有一个有趣的讨论,但丹史密斯最后的评论似乎指出:
对此特定测试用例的重要观察:方法引用的"限定类型"(即字节码命名的类)应与调用的限定类型相同:接收器的类型.javac使用声明类的类型是错误的.见JDK-8059632.
修复该错误,我认为不同捕获类型的问题消失了.
| 归档时间: |
|
| 查看次数: |
665 次 |
| 最近记录: |