Java8:Lambda序列化

最近我一直在考虑为Tyrus项目作一个优化处理,容许用户跨越集群向链接到一个URL的一部分客户端进行广播。 有不少方法能够达成目标。但自从使用了 JDK 8 后,这个问题简已经变成了个人眼中钉。html

为了达到这个目的,我建立了一个简单的单元测试。经过过滤器将它序列化到磁盘上、读取而后执行。咱们能够直接或间接地引用它的一个实例字段 “VALUE”,以此来查出到底是什么致使了序列化失败。java

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));
    }
  }
}

既然只是为了校对,咱们可让匿名内部类测试失败,由于它老是包含了一个宿主类的对象的引用……ide

@Test(expected = NotSerializableException.class)
public void testAnonymousDirect() throwsIOException, ClassNotFoundException { 

    String value = VALUE;  

    filter(newSerializablePredicate<String>() { 

         @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<String> {
    @Override
    public boolean test(String t) {
      // TODO Implement this method
      return 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;
  }

  @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如今被正确地序列化而且恢复了。this

@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进行序列化。code

原文连接: dzone 翻译: ImportNew.com - 黄飞飞
译文连接: http://www.importnew.com/8554.html
htm

相关文章
相关标签/搜索