How to define a function using Serializable lambda parameter as parameter

Is it possible to declare a method taking a Serializable lambda as a parameter without declaring a dedicated interface or asking the client to cast a lambda ?

Let's 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 expected is NotSerializableException

selected.

To make it work, we can use lambda to add an additional Serializable binding.

  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 frustrating as it forces each caller to use a different lambda and the method signature indicates that it f

should be serializable. It is verbose and error prone.

To remove the template and make it 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 satisfies my needs. The only downside to 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 an additional interface and declare multiple bounds directly in the method signature?

+3


source to share


1 answer


I know this question is quite old, but since it has no answer, I will try to try it.

However, this solution is frustrating as it forces every caller to cast their lambda and the method signature shows that f should be serialized. It is verbose and error prone.

Although this solution still requires you to declare that your lambda expression also implements the Serializable interface, this requires require .



So it gives an error when not implemented. It also allows the use of Children functions if they do not implement 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"

}

      

+1


source







All Articles