I am not sure where are you seeing Predicate<List>. The section that you are referring to uses Predicate<Car>.
However, assuming that you really are interested in Predicate<List> and in knowing why (ArrayList al) -> al.isEmpty() can't implement Predicate<List>:
A lambda expression that implements Predicate<List> must satisfy the contract imposed by Predicate<List>, which means it must be able to transform to a class that implements the abstract method declared by Predicate<List> i.e. boolean test(List ). Something like this:
Code: Select all
class Lambda1 implements Predicate<List>{
public boolean test(List l){ //correctly implements the method declared by Predicate<List>.
return l.isEmpty();
}
}
But the expression (ArrayList al) -> al.isEmpty() translates to:
Code: Select all
class Lambda2 implements Predicate<List>{
public boolean test(ArrayList l){
return l.isEmpty();
}
}
But the Lambda2 class violates the rules of interface implementation. This is not a case of "passing" an ArrayList where a List is required. You are not "calling" the test(List ) method here, you are "implementing" the test(List ) method.
This has nothing to do with lambda and Predicate. It is about implementing an interface (any interface for that matter). For example, if you have an interface :
You cannot implement it like this:
Code: Select all
class CX implements X{ //will not compile because CX does not have implementation for X's method.
public void m(ArrayList l){ //this does not implement m(List ) method.
}
}
Because to implement an interface method, the signature must match exactly as specified by the interface (subject to the rule of covariant returns). You have to define m(List ) in CX for it to correctly implement X.
Please let us know if this addresses your doubt and if it does, we will try to make sure this point is covered in the book.