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

Asked

Viewed 89 times

9

Snippet source code from interface Comparator.

Somebody explain to me how this is treated Comparator<T> & Serializable?

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));
}
  • 3

    In grepcode has the option to see the code in text form, click on RAW. I already copied the method of the q vc tried to bring here, anyway.

  • @Article Thanks! It is complicated to post by cell phone heheh

  • 3

    That’s not the bitwise operator. It’s just the same glyph. There it’s kind of saying that the returned object belongs to both interfaces

1 answer

8


This is a lambda:

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

This here is a cast:

(Comparator<T> & Serializable)

That one cast causes the lambda to be interpreted as being of the type Comparator<T> & Serializable.

The guy Comparator<T> & Serializable 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, and so this is a feature of the language that you’ll only see being applied to real code once in a while.

In this case, when using the cast from one lambda to another type, the compiler types inferrer will be induced to infer as lambda type, the type pointed in the 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 type of return is this type intersection. 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 the realization of a lambda to be also serialized, preventing the occurrence of a java.io.NotSerializableException in the event of an attempt to serialize an object in one of its fields-transient, the object returned by the method comparing.

  • 2

    The intention I had "fished" from the code, and I think I’ve seen something like that in Generics, but I didn’t know it worked in Casts.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.