lambda 序列化
因此,我一直在思考Tyrus项目所需的增强功能,该功能允许用户广播到跨机器集群连接到URL的客户端子集。 有多种方法可以做到这一点。 但是自从我使用JDK 8以来,这个问题肯定看起来像钉子。
为此,我创建了一个简单的单元测试类,该类将使用过滤器,将其序列化到磁盘,读回然后执行。 它有一个实例字段“ VALUE”,我们可以使用它直接或间接引用以找出导致序列化失败的原因。
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.NotSerializableException;
import java.io.ObjectInput;
import java.io.ObjectInputStream;
import java.io.ObjectOutput;
import java.io.ObjectOutputStream;
import java.io.Serializable;import java.util.function.Predicate;import org.junit.Test;public class SerializablePredicateFilterTest {public String VALUE = "Bob";public interface SerializablePredicate<T> extends Predicate<T>, Serializable {}public <T> void filter(SerializablePredicate<T> sp, T value) throws IOException, ClassNotFoundException {sp.getClass().isLocalClass();File tempFile = File.createTempFile("labmda", "set");try (ObjectOutput oo = new ObjectOutputStream(new FileOutputStream(tempFile))) {oo.writeObject(sp);}try (ObjectInput oi = new ObjectInputStream(new FileInputStream(tempFile))) {SerializablePredicate<T> p = (SerializablePredicate<T>) oi.readObject();System.out.println(p.test(value));}}}
因此,为了进行校准,请确保匿名内部类将失败,因为它始终包含对封闭对象的引用……。
@Test(expected = NotSerializableException.class)public void testAnonymousDirect() throws IOException, ClassNotFoundException {String value = VALUE;filter(new SerializablePredicate<String>() {@Overridepublic boolean test(String t) {return value.length() > t.length();}}, "Bob");}
本地类也是如此,您不使用本地类吗?
@Test(expected = NotSerializableException.class)public void testLocalClass() throws IOException, ClassNotFoundException {class LocalPredicate implements SerializablePredicate<String> {@Overridepublic boolean test(String t) {// TODO Implement this methodreturn false;}}filter(new LocalPredicate(), "Bobby");}
因此,当然可以使用独立的类,在这种情况下,为方便起见,可以使用嵌套类。
public static class LengthPredicate implements SerializablePredicate<String> {private String value;public LengthPredicate(String value) {super();this.value = value;}public void setValue(String value) {this.value = value;}public String getValue() {return value;}@Overridepublic boolean test(String t) {// TODO Implement this methodreturn false;}}@Testpublic void testStaticInnerClass() throws IOException, ClassNotFoundException {filter(new LengthPredicate(VALUE), "Bobby");}
因此,让我们开始使用JDK 8,事实证明,我的第一次尝试也失败了,但是它确实确认序列化对于使用Lambda非常满意。
@Test(expected = NotSerializableException.class)public void testLambdaDirect() throws IOException, ClassNotFoundException {filter((String s) -> VALUE.length() > s.length(), "Bobby");}
稍作修改即可将值复制到有效的最终属性中,现在可以lambda进行序列化并正确检索。
@Testpublic void testLambdaInDirect() throws IOException, ClassNotFoundException {String value = VALUE;filter((String s) -> value.length() > s.length(), "Bobby");}
当然,如果该值是一个简单的方法参数,它也可以正常工作。
@Testpublic void testLambdaParameter() throws IOException, ClassNotFoundException {invokeWithParameter(VALUE);}private void invokeWithParameter(String value) throws java.lang.ClassNotFoundException, java.io.IOException {filter((String s) -> value.length() > s.length(), "Bobby");}
因此答案是肯定的,如果您稍加小心,就可以将其序列化。
参考: Lambda,会序列化吗? 来自我们的JCG合作伙伴 Gerard Davison,来自Gerard Davison的博客博客。
翻译自: https://www.javacodegeeks.com/2013/12/lambda-will-it-serialize.html
lambda 序列化