Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java 8 Functional interface assignment context

Tags:

java

java-8

Question is regarding assignment context of functional interface-

Predicate<String> p = String::isEmpty;

Works fine where the isEmpty method declaration in String class is - public boolean isEmpty(){}.

If I try to declare same in custom class like -

class Test{
   public boolean isEmpty(){
       ...
   }
}

And make same assignment -

Predicate<String> p = Test::isEmpty;

It would be compilation error -

The type Test does not define isEmpty(String) that is applicable here

And Predicate<T> represents a predicate (boolean-valued function) of one argument and functional method is boolean test(T t){}.

Any explanation? And am I missing anything?

like image 420
Subhrajyoti Majumder Avatar asked Aug 08 '14 06:08

Subhrajyoti Majumder


1 Answers

You should have:

Predicate<Test> p = Test::isEmpty;

and not

Predicate<String> p = Test::isEmpty;

There is no String in

class Test {
    public boolean isEmpty(){
           ...
    }
}

so why should there be Predicate<String> ?

See the tutorial of method references. What you have here is the 3rd case "Reference to an instance method of an arbitrary object of a particular type".

Having

Predicate<String> p = String::isEmpty();
String s = "";

Calling p.test(s); is the same as callign s.isEmpty(); so that's why you cannot give as argument a String to call a method from Test.

It would have been possible to have a common Predicate if both String and Test would implement an interface Empty with the method boolean isEmpty() and then to have Predicate<Empty>. Then both p.test(string) and p.test(test) would work; otherwise it won't, Java has strong typing and does not support duck typing.

like image 191
Random42 Avatar answered Sep 20 '22 21:09

Random42