Core Java

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.

Greg Higgins

Originally a mechanical engineer, Greg has been working in IT for the last 18 years. Greg has held a variety of roles over the years, but in the last 9 years he has concentrated on writing systems in the High Frequency Trading space. He is the creator and maintainer of fluxtion event processing framework (https://github.com/v12technology/fluxtion)
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Inline Feedbacks
View all comments
Back to top button