Сериализация лямбда после ее создания

Я могу сериализовать lambda со следующим синтаксисом:

Runnable r = (Runnable & Serializable) () -> System.out.println("");
try (ObjectOutput oo = new ObjectOutputStream(new ByteArrayOutputStream())) {
  oo.writeObject(r);
}

Однако, если я получаю лямбда из клиентского кода, и он не был передан соответствующим образом, я не могу его сериализовать.

Как я могу сериализовать r ниже без изменения его определения:

Runnable r = () -> System.out.println("");

Я попытался сериализовать "производный" объект:

Runnable r1 = (Runnable & Serializable) r::run;
Runnable r2 = (Runnable & Serializable) () -> r.run();

но в каждом случае oo.writeObject(rxxx); выходит из строя с NotSerializableException.

Ответ 1

Это правильно и по дизайну. Так же, как вы не можете взять несериализуемый объект и сделать его сериализуемым после создания экземпляра, после создания лямбда его сериализуемость установлена.

Lambda является сериализуемым, если его целевой тип сериализуем (и его захваченные аргументы сериализуемы.) Ваш первый пример сериализуем, потому что целевой тип - это пересечение (Runnable и Serializable). Ваши две попытки конвертировать r завершаются сбоем, потому что в обоих случаях r - это захваченная переменная, которая не является сериализуемой, и поэтому полученная ссылка lambda expression/method не является сериализуемой. (Приемник для ссылки связанного метода действует как захваченная переменная.)