如何定义一个以Serializable lambda作为参数的函数

时间:2015-06-28 21:27:03

标签: java serialization lambda

是否可以声明一个方法,将Serializable lambda作为参数,而不必声明专用接口或要求客户端cast the lambda

让我们用这个玩具示例来说明我的问题:

 static <T, R> void serialize(Function<T, R> f) throws IOException {
    try (ObjectOutputStream oos = new ObjectOutputStream(new ByteArrayOutputStream())) {
      oos.writeObject(f);
    }
  }

  public static void main(String[] args) throws IOException {
    serialize(e -> e);
  }

默认情况下,Lambdas不可序列化,并且会抛出预期的NotSerializableException

为了使它工作,我们可以转换lambda来添加一个额外的Serializable绑定。

  static <T, R> void serialize(Function<T, R> f) throws IOException {
    try (ObjectOutputStream oos = new ObjectOutputStream(new ByteArrayOutputStream())) {
      oos.writeObject(f);
    }
  }

  public static void main(String[] args) throws IOException {
    serialize((Function<Object, Object> & Serializable) e -> e);
  }

但是,这个解决方案令人不快,因为它会强制每个调用者强制转换lambda,方法签名确实显示f必须是可序列化的。它冗长且容易出错。

要删除样板并使其类型安全,我们可以定义专用接口:

  interface SerFunction<T, R> extends Function<T, R>, Serializable { }

  static <T, R> void serialize(SerFunction<T, R> f) throws IOException {
    try (ObjectOutputStream oos = new ObjectOutputStream(new ByteArrayOutputStream())) {
      oos.writeObject(f);
    }
  }

  public static void main(String[] args) throws IOException {
    serialize(e -> e);
  }

它完成了这项工作,几乎满足了我的需求。这种模式的唯一缺点是我必须在每个功能接口的顶部创建一个专用接口,这有点麻烦。是否有可能获得额外接口并直接在方法签名中声明多个边界?

1 个答案:

答案 0 :(得分:1)

我知道这个问题已经过时了,但由于它没有答案,我会试一试。

  

然而,这种解决方案令人不愉快,因为它会强制每个来电者   施放他们的lambda,方法签名确实表明f必须是   序列化。它冗长且容易出错。

即使此解决方案仍然需要您声明您的lambda表达式也实现了Serializable接口,但这样做 require

因此,它在未实现时会出错。 它还允许函数的子函数在未实现SerFunction时使用。

public static <T, R, F extends Function<T, R> & Serializable> void serialize(F f) throws IOException
{
    try (ObjectOutputStream oos = new ObjectOutputStream(new ByteArrayOutputStream()))
    {
        oos.writeObject(f);
    }
}

public static void main(String[] args) throws IOException
{
    serialize((Function<Object, Object> & Serializable) e -> e);
    // all happy

    serialize((Function<Object, Object>) e -> e);
    // compiler error "no instance(s) of type variable(s) exist so that Function<Object, Object> conforms to Serializable
    // inference variable F has incompatible bounds:
    // lower bounds: Function<Object, Object>
    // upper bounds: Function<T, R>, Serializable"

}