Reputation: 1209
In the below code I have this line: stream.filter(Data::isEven);
I am using a filter()
and a filter()
accepts a Predicate
interface as parameter. We all know that Predicate
has one method with the signature: public boolean test(T t);
which accepts one parameter and returns a boolean.
I am of the understanding that the isEven()
method that accepts no parameter is not a valid Predicate because unlike test()
method it does not take any parameter, so how come my code is not showing a compile time error?
import java.util.stream.Stream;
public class Main App {
public static void main(String args[]) {
Stream<Data> stream =
Stream.of(new Data(4), new Data(1));
stream.filter(Data::isEven); // should throw compile error but doesn't
}
}
class Data{
int i;
public Data(int i) {
this.i=i;
}
public boolean isEven() {
return i%2==0;
}
}
Upvotes: 3
Views: 365
Reputation: 16910
The thing is that Data::isEven
is a method reference equivalent to data -> data.isEven()
predicate :
Predicate<Data> predicate = data -> data.isEven();
// is the same as
Predicate<Data> predicate= Data::isEven;
This is described in JLS 15.13
:
The target reference of an instance method (§15.12.4.1) may be provided by the method reference expression using an
ExpressionName
, aPrimary
, orsuper
, or it may be provided later when the method is invoked.....
Evaluation of a method reference expression produces an instance of a functional interface type (§9.8). Method reference evaluation does not cause the execution of the corresponding method; instead, this may occur at a later time when an appropriate method of the functional interface is invoked.
In your case Data::isEven
is a reference to instance method isEven
of Data
object.
Upvotes: 2
Reputation: 2565
As others wrote "Data::isEven" or "data -> data.isEven()" is Predicate here. When we invoke test method of this predicate, we pass the instance of data (you have a stream of such instances) there as a parameter.
Upvotes: 1
Reputation: 2763
Data::isEven
is a Predicate
.
To call this method you have to pass value, like: myData.isEven()
.
This is the same as it would be isEven(myData)
. So the difference is only in syntax (parameter either before a dot, or inside parenthesis), but semantically it is the same.
Therefore isEven
is a Predicate<Data>
because it accepts Data
and returns Boolean
.
Upvotes: 1