Невозможно десериализовать lambda

Так же, как небольшой проект, я пытаюсь сделать нечто вроде считывания сериализованных lambdas (локально или с FTP) и вызывает их функции запуска как часть теста для экспериментов с ассоциациями файлов в Windows (т.е. открытие определенных типов файлов открывает их с определенной программой) и еще много чего, но независимо от того, что я пытаюсь, он никогда не кажется должным образом десериализованным.

Лямбда была объявлена ​​так

Runnable r = (Runnable & Serializable) () -> { // blah blah // made sure not to capture anything }; 

и сериализован с использованием FileOutputStream, завернутый в [n optional] BufferedOutputStream, завершенный ObjectOutputStream без проблем. Однако, когда десериализован [в другом проекте], он терпит неудачу, заявив, что он не смог найти охватывающий class, содержащий код для его сериализации. Я пробовал различные вещи, например, обертывать их в сериализуемый class (w / serialVersionUID = 0L для целей тестирования) или определять интерфейс, который расширяет Runnable и Serializable, но безрезультатно.

Да, я знаю, что сериализация lambdas на самом деле не очень хорошая практика (или, как нам сказали), но я не уверен, как переходить функции и подпрограммы во что-то, что я могу хранить как файл или FTP. Если это даже не правильный путь, расскажите.

О, я использую Eclipse Luna из любой последней версии.

Редактировать:

Дезериализованный

 File f = new File(somePath); FileInputStream fish = new FileInputStream(f); BufferedInputStream bos = new BufferedInputStream(fish); // not really necessary ObjectInputStream ois = new ObjectInputStream(bos); Runnable r = (Runnable) ois.readObject(); ois.close(); r.run(); 

Вы не можете десериализовать объект без classа, определяющего его. Это не изменилось с lambda-выражениями.

Лямбда-выражения немного сложнее, поскольку их сгенерированный class времени выполнения не является classом, который его определял, но их определяющий class является тем, у кого есть код тела лямбды, а в случае сериализуемых lambda – метод поддержки десериализации, который вызывается для проверки и повторное создание экземпляра лямбды.

См. Раздел SerializedLambda :

Ожидается, что разработчики сериализуемых lambdas, таких как компиляторы или языковые библиотеки времени выполнения, гарантируют, что экземпляры десериализуются должным образом. Один из них означает, что метод writeReplace возвращает экземпляр SerializedLambda , а не разрешает сериализацию по умолчанию.

SerializedLambda имеет метод readResolve который ищет (возможно частный) статический метод $deserializeLambda$(SerializedLambda) в classе захвата, вызывает его с собой как первый аргумент и возвращает результат. Лямбда-classы, реализующие $deserializeLambda$ , отвечают за проверку того, что свойства SerializedLambda согласуются с лямбдой, фактически захваченной этим classом.

Поэтому даже если ваш экземпляр не ссылался на синтетический метод внутри определяющего classа (например, в случае ссылки метода на метод вне этого classа), десериализация все еще требует $deserializeLambda$ для правильной проверки правильности экземпляра.


Что касается «хорошей практики» сериализации lambda, имейте в виду, что lambda-выражения инкапсулируют поведение , а не состояние. Сохранение поведения всегда подразумевает сохранение только некоторой ссылки и требует кода, предназначенного для ее восстановления, для реализации связанного с ней поведения. Это также сработает, если вы просто ссылаетесь на предполагаемое поведение с помощью символического имени или просто сохраняете, например, связанные значения enum .

В этом вопросе объясняется более подробно вопрос о возможности сериализации lambda.

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

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

  • В чем разница между привязкой лямбды и метода на уровне выполнения?
  • Сохранение / загрузка данных в Unity
  • gwt - Использование списка в вызове RPC?
  • Ошибка JSON.NET Локальный цикл привязки для типа
  • JSON.Net выдает StackOverflowException при использовании
  • Обнаружено, что
  • Почему java.util.Optional не является Serializable, как сериализовать объект с такими полями
  • Использование readObject / writeObject в сериализации
  • Заставить JSON.NET включать миллисекунды при сериализации DateTime (даже если компонент ms равен нулю)
  • Может ли Json.NET сериализовать / десериализовать в / из streamа?
  • Сериализация OpenCV Mat_
  • Interesting Posts

    Привод 4TB показывает только 1.6TB?

    Почему wait () всегда должен находиться в синхронизированном блоке

    «Npm install» устанавливает все зависимости в каталоге node_modules, вместо того, чтобы иметь вложенные

    Android TextView Linkify перехватывает с родительским жестом просмотра

    Мониторинг вызовов приложений в DLL

    В чем разница между иварами и свойствами в Objective-C

    Что такое возврат каретки, перевод строки и фид?

    Как я могу дать компилятору Intellij больше места для кучи?

    Преобразование таблицы mysql в исходный dataset очень медленное по сравнению с CSV-файлом

    onKeyListener не работает с мягкой клавиатурой (Android)

    Установите определенные порты USB только для перезагрузки

    Как просмотреть данные в файле sqlite, запущенном в приложении iphone?

    Удаленный раздел Linux и теперь Grub Rescue Shows Up

    Как отображать элементы в Canvas через Binding

    Windows 7: ошибка извлечения запоминающего устройства USB

    Давайте будем гением компьютера.