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
InnerClassLambdaMetafactory
pour toujours générer le code requirejs pour la sérialisation LambdaMetaFactory
lors de la désérialisation Pour plus de détails et le code, voir cet article de blog