比来我一贯在斟酌为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 extends Predicate, Serializable {}
public void filter(SerializablePredicate 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 p = (SerializablePredicate) oi.readObject();
System.out.println(p.test(value));
}
}
}
既然只是为了校正,我们可以让匿名内部类测试丢失落败,因为它老是包括了一个宿主类的对象的引用……
@Test(expected = NotSerializableException.class)
public void testAnonymousDirect() throwsIOException, ClassNotFoundException {
String value = VALUE;
filter(newSerializablePredicate() {
@Override
public boolean test(String t) {
return value.length() > t.length();
}
}, "Bob");
}
对外埠类来说一样如斯, 外埠类有什么弗成以行使呢?
@Test(expected = NotSerializableException.class)
public void testLocalClass() throws IOException, ClassNotFoundException {
class LocalPredicate implements SerializablePredicate {
@Override
public boolean test(String t) {
// TODO Implement this method
return false;
}
}
filter(new LocalPredicate(), "Bobby");
}
一个自力的类虽然可以责任,在这个示例中为了随意起见行使了一个嵌套类。
public static class LengthPredicate implements SerializablePredicate {
private String value;
public LengthPredicate(String value) {
super();
this.value = value;
}
public void setValue(String value) {
this.value = value;
}
public String getValue() {
return value;
}
@Override
public boolean test(String t) {
// TODO Implement this method
return false;
}
}
@Test
public void testStaticInnerClass() throws IOException, ClassNotFoundException {
filter(new LengthPredicate(VALUE), "Bobby");
}
我们照样行使JDK
8,效果证实我的第一个try也丢失落败了。但它证清晰了了,常日情形下序列化长短常情愿收受接管一个Lambda表达式的。
@Test(expected = NotSerializableException.class)
public void testLambdaDirect() throws IOException, ClassNotFoundException {
filter((String s) -> VALUE.length() > s.length(), "Bobby");
}
略微做下修改,拷贝值到一个有用的final属性中。瞧,lambda现在被准确地序列化而且恢复了。
@Test
public void testLambdaInDirect() throws IOException, ClassNotFoundException {
String value = VALUE;
filter((String s) -> value.length() > s.length(), "Bobby");
}
虽然,假定value是一个简略方法的参数,也可以责任正常。
@Test
public 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中止序列化。
style="display:inline-block;width:336px;height:280px"
data-ad-client="ca-pub-9611302475373562"
data-ad-slot="8266948139">