Статьи

Сохраните свои лямбды на черный день — сохраните в файл

Вступление

Короткий пост, описывающий, как лямбда Java может быть сохранена в файл для повторного использования в другом процессе.

Сериализация Lambdas

Лямбды, представленные в Java 8, делают функции первоклассными гражданами (почти) на языке Java. Они устраняют необходимость в выделенном классе для хранения функции. Но как это работает под одеялом?

В действительности javac захватывает класс, содержащий функцию, добавляя статический метод, который содержит реализацию функции. Сайт вызова функции заменяется вызовом вновь добавленного статического метода. Для полного описания волшебства лямбда-реализации смотрите это
статья

Oracle услужливо предоставляет класс SerializableLambda, который реализует сериализуемую форму лямбды, предоставляя достаточное количество метаинформации для восстановления вызова. Все, что нам нужно сделать, — это преобразовать лямбду в Serializable, а затем использовать стандартные стандартные механизмы для упорядочения лямбды. Ниже приведено несколько полезных функций для сериализации и десериализации лямбды.

01
02
03
04
05
06
07
08
09
10
11
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();
    }
}

В функции сериализации я использую пересекающиеся типы, чтобы привести функцию к Serializable. Есть небольшой проект с тестовой базой
здесь, чтобы продемонстрировать сериализацию. Основной метод выполнения функций:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
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();
        }
    }
 
}

У проекта есть серийная лямбда-функция «func-1» в корне. При запуске проекта func-1 будет перезаписан, поэтому второе выполнение даст результат, отличный от первого:

Первое исполнение:

привет — Грег

до свидания — Грег

Второе исполнение:

до свидания — Грег

до свидания — Грег

Надеюсь, вам понравилась эта небольшая статья и она показалась вам интересной.

Опубликовано на Java Code Geeks с разрешения Грега Хиггинса, партнера нашей программы JCG . См. Оригинальную статью здесь: сохраните свои лямбды на черный день — сохраните в файл

Мнения, высказанные участниками Java Code Geeks, являются их собственными.