Question:
Comparator interface source code snippet.
Can someone explain to me how this Comparator<T> & Serializable
is handled?
public static <T, U extends Comparable<? super U>> Comparator<T> comparing(
Function<? super T, ? extends U> keyExtractor)
{
Objects.requireNonNull(keyExtractor);
return (Comparator<T> & Serializable)
(c1, c2) -> keyExtractor.apply(c1).compareTo(keyExtractor.apply(c2));
}
Answer:
This here is a lambda:
(c1, c2) -> keyExtractor.apply(c1).compareTo(keyExtractor.apply(c2));
This here is a cast :
(Comparator<T> & Serializable)
This cast causes the lambda to be interpreted as being of type Comparator<T> & Serializable
.
The Comparator<T> & Serializable
type is an intersection type, which means Comparator<T>
and Serializable
at the same time. The use of intersection types is a very rare thing to see in Java, so this is a feature of the language that you will only see applied in real code once in a while.
In this case, when using the cast of a lambda to another type, the compiler's type inferr will be induced to infer as a type of the lambda, the type pointed to in the cast . That is, the part of the compiler that tries to guess the type of the parameters and the return of the lambda will end up concluding that the return type is this intersection type. Since Comparator<T>
has only one abstract method, Serializable
has no abstract methods and both are interfaces, so this type is representable by a lambda.
The compiler will see this code, as something roughly equivalent to this:
public static <T, U extends Comparable<? super U>> Comparator<T> comparing(
Function<? super T, ? extends U> keyExtractor)
{
Objects.requireNonNull(keyExtractor);
class Temp implements Comparator<T>, Serializable {
@Override
public int compare(T c1, T c2) {
return keyExtractor.apply(c1).compareTo(keyExtractor.apply(c2));
}
}
return new Temp();
}
The purpose of doing this is to allow an object that is the realization of a lambda to also be serializable, preventing a java.io.NotSerializableException
from occurring in the event of an attempt to serialize an object that has one of its non- transient
fields, the object returned by the comparing
method.