简体   繁体   English

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

[英]How to define a function taking a Serializable lambda as parameter

Is it possible to declare a method taking a Serializable lambda as parameter without having to declare a dedicated interface or ask the client to cast the lambda ? 是否可以声明一个方法,将Serializable lambda作为参数,而不必声明专用接口或要求客户端转换lambda

Lets use this toy example to illustrate my question: 让我们用这个玩具示例来说明我的问题:

 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 are not Serializable by default, and the expected NotSerializableException is thrown. 默认情况下, NotSerializableException不是Serializable,并且抛出了预期的NotSerializableException

To make it work, we can cast the lambda to add an additional Serializable bound. 为了使它工作,我们可以转换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);
  }

However, this solution is unpleasant since it forces every caller to cast their lambda and the method signature does show that f must be serializable. 但是,这个解决方案令人不快,因为它会强制每个调用者抛出它们的lambda,方法签名确实表明f必须是可序列化的。 It is verbose and error prone. 它冗长且容易出错。

To remove the boilerplate and make it type safe, we can define a dedicated interface: 要删除样板并使其类型安全,我们可以定义一个专用接口:

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

It does the job and almost suit my needs. 它完成了这项工作,几乎满足了我的需求。 The only drawback of this pattern is that I have to create a dedicated interface on top of each functional interface which is a bit cumbersome. 这种模式的唯一缺点是我必须在每个功能接口的顶部创建一个专用接口,这有点麻烦。 Is it possible to get ride of the extra interface and declare the multiple bounds directly in the method signature ? 是否有可能获得额外接口并直接在方法签名中声明多个边界?

I know this question is quite old, but as it doesn't have an answer, I'll give it a try. 我知道这个问题很老了,但由于没有答案,我会试一试。

However, this solution is unpleasant since it forces every caller to cast their lambda and the method signature does show that f must be serializable. 但是,这个解决方案令人不快,因为它会强制每个调用者抛出它们的lambda,方法签名确实表明f必须是可序列化的。 It is verbose and error prone. 它冗长且容易出错。

Even though this solution will still require you to state that your lambda expression also implements the Serializable interface, this does require you to do so. 尽管此解决方案仍然需要您声明您的lambda表达式也实现了Serializable接口,但这确实需要您这样做。

So, it gives an error when it is not implemented. 因此,它在未实现时会出错。 It also allows children of Function to be used when they do not implement SerFunction. 它还允许函数的子函数在未实现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"

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM