Shahid Sarwar
Shahid Sarwar

Reputation: 1209

I think that the Stream.filter() is not showing compile time error even with an invalid predicate

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

Answers (3)

Michał Krzywański
Michał Krzywański

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, a Primary, or super, 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

nickolay.laptev
nickolay.laptev

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

Max Farsikov
Max Farsikov

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

Related Questions