Search code examples
lambdajava-8method-referencefunctional-interface

Assigning method references to Functional Interfaces


Java 8+ allows assigning method references to Functional Interfaces.

Then what is the problem with below code (jdoodle link) -

public void newMethod(){
    
    Predicate p = String::isBlank;
    
}

Different from the error in jdoodle compilation, in my local (gist link) i get error:

Non-static method cannot be referenced from a static context

But - below thing worked

 Predicate<String> pp = String::isBlank; //this thing works

Solution

  • This is because you are using a raw type - Predicate. The function type of a raw functional interface is:

    The function type of the raw type of a generic functional interface I<...> is the erasure of the function type of the generic functional interface I<...>.

    The function type for the generic Predicate<T> is (T) -> boolean (pardon my own original syntax here), a function that takes in a T and returns a boolean. Therefore, the function type of the raw Predicate is (Object) -> boolean, the erasure of (T) -> boolean.

    This means that it is possible to assign Objects::isNull to such a raw functional interface (but you shouldn't use raw types in the first place):

    // Objects::isNull takes an Object and returns a boolean, so this compiles
    Predicate x = Objects::isNull;
    

    The method reference String::blank only takes a String, not any kind of Object. Therefore it is not congruent with the the function type (Object) -> boolean and hence cannot be assigned to a variable of type Predicate.

    If Predicate p = String::isBlank; had worked, then you would be able to do something like p.test(1). And String::isBlank would have to magically determine whether 1 "is blank".

    The error message here is admittedly a bit confusing.

    For Predicate<String>, the definition of its function type is different, and it has the function type (String) -> boolean, which the method reference String::isBlank is congruent to.

    The function type of a parameterized functional interface type I<A1...An>, where A1...An are types and the corresponding type parameters of I are P1...Pn, is derived by applying the substitution [P1:=A1, ..., Pn:=An] to the function type of the generic functional interface I<P1...Pn>.