1

I have no idea why it's not working.

Error message in eclipse: The method test(Fruit, capture#1-of ? extends Fruit) in the type BiPredicate is not applicable for the arguments (Fruit, Mango)

import java.util.function.BiPredicate;

public class PredTest {

    public static void main(String[] args) {

        class Fruit {
            public String name;
            public String color;
            Fruit(String name) {this.name = name; }
        };

        class Apple extends Fruit {
            Apple() {super("Apple");}
        };
        class Mango extends Fruit {
            Mango() {super("Mango");}
        };

        BiPredicate<Fruit, ? extends Fruit> tester = (f, nf) -> {
            System.out.println(nf.name);
            return true;
        };
        Fruit f = new Fruit("Not named");
        Apple a = new Apple();
        Mango m = new Mango();

// ########### I see error in the below line
        System.out.println(tester.test(f, m));

    }

}
Ajeetkumar
  • 1,108
  • 4
  • 12
  • 28

1 Answers1

3

Suppose you changed your lambda expression to:

    BiPredicate<Fruit, ? extends Fruit> tester = (Fruit f, Apple nf) -> {
        System.out.println(nf.name);
        return true;
    };

Would you still expect the compiler to allow passing a Mango to this BiPredicate?

Based on the compile time type - BiPredicate<Fruit, ? extends Fruit> - of tester, the compiler doesn't know if Mango is allowed, so it doesn't allow it.

Changing your BiPredicate to:

BiPredicate<Fruit, ? super Fruit> tester = (f, nf) -> {
    System.out.println(nf.name);
    return true;
};

will eliminate the compilation error.

Eran
  • 359,724
  • 45
  • 626
  • 694
  • But how can it then access `nf.name`, if `nf` could be any superclass of `Fruit` (eg `Object`)? – daniu Nov 22 '18 at 10:41
  • 1
    @daniu `BiPredicate` could be assigned a `BiPredicate`, so you can't pass an `Object` to `tester.test()`. – Eran Nov 22 '18 at 10:50
  • But `BiPredicate` could also be assigned a `BiPredicate`, no? – daniu Nov 22 '18 at 13:12
  • 1
    @daniu yes, but then the lambda expression won't contain `nf.name`. And anyway, the compiler can't allow you to pass `Object` as the second parameter of the BiPredicate's method, since your code must be type safe for any possible assignment to the `BiPredicate` variable. – Eran Nov 22 '18 at 13:18