Is it possible to declare a method taking a Serializable lambda as parameter without having to declare a dedicated interface or ask the client to cast the lambda ?
Lets use this toy example to illustrate my question:
static <T, R> void serialize(Function<T, R> f) throws IOException {
try (ObjectOutputStream oos = new ObjectOutputStream(new ByteArrayOutputStream())) {
oos.writeObject(f);
}
}
public static void main(String[] args) throws IOException {
serialize(e -> e);
}
Lambdas are not Serializable by default, and the expected NotSerializableException
is thrown.
To make it work, we can cast the lambda to add an additional Serializable bound.
static <T, R> void serialize(Function<T, R> f) throws IOException {
try (ObjectOutputStream oos = new ObjectOutputStream(new ByteArrayOutputStream())) {
oos.writeObject(f);
}
}
public static void main(String[] args) throws IOException {
serialize((Function<Object, Object> & Serializable) e -> e);
}
However, this solution is unpleasant since it forces every caller to cast their lambda and the method signature does show that f
must be serializable. It is verbose and error prone.
To remove the boilerplate and make it type safe, we can define a dedicated interface:
interface SerFunction<T, R> extends Function<T, R>, Serializable { }
static <T, R> void serialize(SerFunction<T, R> f) throws IOException {
try (ObjectOutputStream oos = new ObjectOutputStream(new ByteArrayOutputStream())) {
oos.writeObject(f);
}
}
public static void main(String[] args) throws IOException {
serialize(e -> e);
}
It does the job and almost suit my needs. The only drawback of this pattern is that I have to create a dedicated interface on top of each functional interface which is a bit cumbersome. Is it possible to get ride of the extra interface and declare the multiple bounds directly in the method signature ?