I am aware that to make Java 8 Consumer serializable I have to cast it:
return (Consumer<Type> & Serializable) () -> {...}
That works fine.
To make is easier I have introduced my own SerializableConsumer
that implements java.io.Serializable
and I use it in my APIs:
private interface SerializableConsumer<T> extends Consumer<T>, Serializable {}
Now I want whenever someone uses SerializableConsumer#andThen()
to return again a consumer that is serializable.
Here are my attempts but so far I cannot make it work. Any ideas are welcome!
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.function.Consumer;
public class SerializeLambdas {
private interface SerializableConsumer<T> extends Consumer<T>, Serializable {}
// attempt 1
private interface SerializableConsumerAndThen<T> extends Consumer<T>, Serializable {
@Override
default SerializableConsumerAndThen<T> andThen(Consumer<? super T> after) {
return (SerializableConsumerAndThen<T>) Consumer.super.andThen(after);
}
}
// attempt 2
private interface SerializableConsumerAndThen2<T> extends Consumer<T>, Serializable {
@Override
default Consumer<T> andThen(Consumer<? super T> after) {
return (Consumer<T> & Serializable) (T t) -> { accept(t); after.accept(t); };
}
}
private static <T> T serializeCopy(T t) throws Exception {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(t);
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bais);
return (T) ois.readObject();
}
public static void main(String[] args) throws Exception {
// this works!
SerializableConsumer<String> consumer = (s) -> System.out.println(s);
SerializableConsumer<String> copy = serializeCopy(consumer);
copy.accept("It works!");
// this doesn't work
SerializableConsumerAndThen<String> consumer2 = (s) -> System.out.println(s);
Consumer<String> consumerAndThen = consumer2.andThen((s2) -> System.out.println(s2));
Consumer<String> copy2 = serializeCopy(consumerAndThen);
copy2.accept("SerializableConsumerAndThen works!");
// this doesn't work too
SerializableConsumerAndThen2<String> consumer3 = (s) -> System.out.println(s);
Consumer<String> consumerAndThen2 = consumer3.andThen((s2) -> System.out.println(s2));
Consumer<String> copy3 = serializeCopy(consumerAndThen2);
copy3.accept("SerializableConsumerAndThen2 works!");
}
}
Both fail with:
Exception in thread "main" java.lang.ClassCastException: java.util.function.Consumer$$Lambda$5/1334729950 cannot be cast to app.SerializeLambdas$SerializableConsumerAndThen
at app.SerializeLambdas$SerializableConsumerAndThen.andThen(SerializeLambdas.java:17)
at app.SerializeLambdas.main(SerializeLambdas.java:46)
....