Save your lambdas for a rainy day – save to file
Introduction
A short post describing how a Java lambda can be persisted to a file for re-use in a different process.
Serialising Lambdas
Lambdas, introduced in Java 8 make functions first class citizens(nearly) in the Java language. They remove the need for a dedicated class to hold the function. But how does this work under the covers?
In reality javac hijacks the class containing the function adding a static method that contains the implementation of the function. The function call site is replaced with an invocation of the newly added static method. For a full description of the lambda implementation magic see this
article.
Oracle helpfully provides the SerializableLambda class that implements the serializable form of a lambda, providing enough meta information to reconstruct the call. All we have to do is cast the lambda to a Serializable and then use standard the standard machinery to marshal the lambda. Below are a couple of utility functions to serialise and deserialise a lambda.
public static <F extends Function & Serializable> void serialise(F f, String name) throws Exception { try (var oos = new ObjectOutputStream(new FileOutputStream(new File(name)))) { oos.writeObject(f); } } public static <T, R, F extends Function<T, R>> F deserialise(String name) throws Exception { try (var ois = new ObjectInputStream(new FileInputStream(name))) { return (F) ois.readObject(); } }
In the serialise function I use intersecting types to cast the function to Serializable. There is a small project with a test main is located
here to demonstrate the serialisation. The main method to execute the functions:
public class Main { public static void main(String[] args) throws Exception { if (false) { serialise(s -> "hello - " + s, "func1"); } System.out.println(deserialise("func1").apply("Greg")); //rewrite func-1 serialise(s -> "goodbye - " + s, "func1"); System.out.println(deserialise("func1").apply("Greg")); } public static <F extends Function & Serializable> void serialise(F f, String name) throws Exception { try (var oos = new ObjectOutputStream(new FileOutputStream(new File(name)))) { oos.writeObject(f); } } public static <T, R, F extends Function<T, R>> F deserialise(String name) throws Exception { try (var ois = new ObjectInputStream(new FileInputStream(name))) { return (F) ois.readObject(); } } }
The project has a serialised lambda “func-1” in the root. Running the project will see func-1 overwritten so the second execution will give a different result from the first:
First execution:
hello – Greg
goodbye – Greg
Second execution:
goodbye – Greg
goodbye – Greg
Hope you enjoyed this small article and found it interesting.
Published on Java Code Geeks with permission by Greg Higgins, partner at our JCG program. See the original article here: Save your lambdas for a rainy day – save to file Opinions expressed by Java Code Geeks contributors are their own. |