Can the & bitwise (and) operator of Java be used for interfaces?

8

Interface source code snippet Comparator .

Does anyone 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));
}
    
asked by anonymous 08.06.2018 / 21:56

1 answer

7

This is a lambda:

(c1, c2) -> keyExtractor.apply(c1).compareTo(keyExtractor.apply(c2));

This is a cast :

(Comparator<T> & Serializable)

This cast causes the lambda to be interpreted as being Comparator<T> & Serializable .

The type Comparator<T> & Serializable is an intersection type, which means Comparator<T> and Serializable at the same time. The use of intersection types is quite rare to see in Java, and so this is a feature of the language you will only see being applied in real code one time or another.

In this case, when using cast from one lambda to another type, the compiler type inference is going to be inferred as lambda type, the type pointed to in cast . That is, the part of the compiler that tries to guess the type of parameters and the return of the lambda will end up concluding that the return type is that 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 more or less 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 performing a lambda to be also serializable, avoiding a java.io.NotSerializableException occurrence in the case of the attempt to serialize some object that has in a of its non-% fields, the object returned by the transient method.

    
08.06.2018 / 23:51