Comment sérialiser un lambda?

Comment puis-je sérialiser avec élégance un lambda?

Par exemple, le code ci-dessous renvoie une NotSerializableException . Comment puis-je le réparer sans créer une interface “factice” SerializableRunnable ?

 public static void main(Ssortingng[] args) throws Exception { File file = Files.createTempFile("lambda", "ser").toFile(); try (ObjectOutput oo = new ObjectOutputStream(new FileOutputStream(file))) { Runnable r = () -> System.out.println("Can I be serialized?"); oo.writeObject(r); } try (ObjectInput oi = new ObjectInputStream(new FileInputStream(file))) { Runnable r = (Runnable) oi.readObject(); r.run(); } } 

Java 8 introduit la possibilité de convertir un object en intersection de types en ajoutant plusieurs limites . Dans le cas de la sérialisation, il est donc possible d’écrire:

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

Et le lambda devient automatiquement sérialisable.

La même construction peut être utilisée pour les références de méthode. Par exemple ce code:

 import java.io.Serializable; public class Test { static Object bar(Ssortingng s) { return "make serializable"; } void m () { SAM s1 = (SAM & Serializable) Test::bar; SAM s2 = (SAM & Serializable) t -> "make serializable"; } interface SAM { Object action(Ssortingng s); } } 

définit une expression lambda et une référence de méthode avec un type de cible sérialisable.

Cast très laid. Je préfère définir une extension Serializable à l’interface fonctionnelle que j’utilise

Par exemple:

 interface SerializableFunction extends Function, Serializable {} interface SerializableConsumer extends Consumer, Serializable {} 

alors la méthode acceptant le lambda peut être définie comme telle:

 private void someFunction(SerializableFunction function) { ... } 

et en appelant la fonction, vous pouvez passer votre lambda sans aucune dissortingbution laide:

 someFunction(arg -> doXYZ(arg)); 

Si vous souhaitez passer à une autre structure de sérialisation telle que Kryo , vous pouvez vous débarrasser des limites multiples ou de la nécessité pour l’interface implémentée d’implémenter Serializable . L’approche est de

  1. Modifier InnerClassLambdaMetafactory pour toujours générer le code requirejs pour la sérialisation
  2. Appelez directement la LambdaMetaFactory lors de la désérialisation

Pour plus de détails et le code, voir cet article de blog