Search code examples
javajava-streammethod-reference

Stream anyMatch accept an method reference not implement Predicate


Stream.anyMatch is defined as:

boolean anyMatch(Predicate<? super T> predicate)

I created a new Class as follows:

class ClassA  {    
    public boolean anyMethodName(Object o) {
        return o instanceof Integer;
    }
}

Then I can run following:

List<String> durunitList = Arrays.asList("h", "d", "w", "m", "y");
ClassA classA = new ClassA();
System.out.println(durunitList.stream().peek(System.out::println).anyMatch(classA::anyMethodName));

But in my ClassA, I haven't implemented Predicate or its functional method:

boolean test(T t)

Why can classA::anyMethodName be stil passed to Stream.anyMatch(...)?


Solution

  • Java 8 added the ability for interfaces to be "functional interfaces" whenever an interface has one abstract method. If they are, the compiler allows you to use a method (either as a lambda or a method reference classA::anyMethodName) like as though it were an instance of that interface, by creating an anonymous class for you (assuming that it has the same return type / parameters).

    Predicate is a functional interface, and as such allows you to directly use your classA::anyMethodName method as though it were an instance of Predicate.

    In the end, your code effectively gets translated into:

    List<String> durunitList = Arrays.asList("h", "d", "w", "m", "y");
    ClassA classA = new ClassA();
    System.out.println(durunitList.stream().peek(System.out::println).anyMatch(new Predicate<String>() {
        @Override
        public boolean test(String o) {
            return classA.anyMethodName(o);
        }    
    }));
    

    ClassA isn't ever casted to Predicate (as it's not a predicate...), but a new anonymous class that does implement Predicate simply calls classA.anyMethodName behind the scenes.