Невозможно десериализовать 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е сериализованного объекта. Вы не можете сериализовать произвольную лямбду и десериализовать ее в другой кодовой базе.

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

  • Использовать имя classа в качестве корневого ключа для сериализации JSON Jackson
  • «Тип не ожидается», используя DataContractSerializer - но это просто class, не смешные вещи?
  • ShouldSerialize * () vs * Условный шаблон условной сериализации
  • Как настроить сериализацию списка объектов JAXB для JSON?
  • ТипNameHandling предостережение в Newtonsoft Json
  • Существуют ли эквиваленты C ++ для функций протокола ввода-вывода протокола Buffer в Java?
  • Получение ServiceStack для сохранения информации о типе
  • Преобразование записей в последовательную форму данных для отправки по HTTP
  • Удаление десериализации JSON в объект с помощью Json.NET
  • C # десериализация структуры после ее получения через TCP
  • Информация о сериализации типов кеша Json.NET?
  • Давайте будем гением компьютера.