
IntPredicate and(IntPredicate p1, IntPredicate p2) {
return p1 && p2;
}
Define Interface
interface IntPredicate {
public IntPredicate and(IntPredicate p1, IntPredicate p2);
}
(a)
IntPredicate pred = x, y -> x && y;
pred.and(p1, p2)
(b)
IntPredicate pred = new IntPredicate() {
public IntPredicate and(IntPredicate p1, IntPredicaate p2) {
return p1 && p2;
}
}
(c)
class Test implements IntPredicate {
public IntPredicate and(IntPredicate p1, IntPredicate p2) {
return p1 && p2;
}
}
Test pred = new Test();
pred.and(p1, p2);
Answers
// Answer
IntPredicate and(IntPredicate p1, IntPredicate p2) {
return x -> p1.test(x) && p2.test(x);
}
// Answer
IntPredicate and(IntPredicate p1, IntPredicate p2) {
return new IntPredicate() {
public boolean test(int x) {
return p1.test(x) && p2.test(x);
}
};
}
// Answer
class AndPredicate implements IntPredicate {
private final IntPredicate p1;
private final IntPredicate p2;
AndPredicate(IntPredicate p1, IntPredicate p2) {
this.p1 = p1;
this.p2 = p2;
}
public boolean test(int x) {
return p1.test(x) && p2.test(x);
}
}
IntPredicate and(IntPredicate p1, IntPredicate p2) {
return new AndPredicate(p1, p2);
}
Learning
interface IntPredicate {
boolean test(int x);
}
// IntPredicate is actually supposed to test something and return true/false
// p1 && p2 doesn't make sense because those are IntPredicate objects, not boolean true/falses

(a) .add adds elements into a list. List<? extends Object> blocks you from adding anything because it’s so generic. You can’t add anything inside because you might put the wrong thing inside. Why can’t you add Object? Because at run time you’re not sure what list actually is.
(b) If it was List<String> the compiler knows precisely what type the list holds, so list.add(“DEF”) is perfectly fine. String s = list.get(0) is okay because whatever the list holds, it’s at least an object. get(n) retrieves the element at index 0
(c) ? super Integer means the list is of some type that is Integer or above — could be List<Integer>, List<Number>, or List<Object>. list.add(new Object()) — blocked because if it’s secretly a List<Integer>, adding a plain Object corrupts it. In fact, list.add(new Object()) would only work if you knew for certain the list is List<Object>
(d) List<?> means a list of completely unknown type.
(e) Generic type cannot be a primitive type. List<? super Integer> list = new ArrayList<int>() doesn’t works. List<? super Integer> list = new ArrayList<Integer>() works.
(f) new ArrayList() is a raw type, without type parameter. It’ll compile because Java keeps backwards compatibility.