Let's say change Comparator.comparing source code from
public static <T, U extends Comparable<? super U>> Comparator<T> comparing(
Function<? super T, ? extends U> keyExtractor)
{
Objects.requireNonNull(keyExtractor);
return (Comparator<T> & Serializable) (c1, c2) -> keyExtractor.apply(c1).compareTo(keyExtractor.apply(c2));
}
to
public static <T, U extends Comparable<? super U>> Comparator<T> comparing(
Function<T, U> keyExtractor)
{
Objects.requireNonNull(keyExtractor);
return (Comparator<T> & Serializable) (c1, c2) -> keyExtractor.apply(c1).compareTo(keyExtractor.apply(c2));
}
And we have the follwing classes
class PhysicalObject {
double weight;
public Double getWeight(){
return weight;
}
}
class Car extends PhysicalObject {}
The following statament does not compile
Function<PhysicalObject, Double> weight = p->p.getWeight();
Comparator<Car> c = HypotheticComparators.comparing(weight);
while this compile Comparator<Car> c3_1 = HypotheticComparators.comparing(PhysicalObject::getWeight);
I understand that the first statement can't compile is because the modified comparing function does not have the bounded wildcard (? super T), but why the second statement can compile without any problem ?
With comparing defined as:
Comparator<T> comparing(Function<T, U> keyExtractor) // abbreviated
the statement:
Comparator<Car> c = comparing(weight);
requires argument to be a Function<Car, ?>, but weight is a Function<PhysicalObject, Double> so you get the compile error.
However, when doing
Comparator<Car> c3_1 = comparing(PhysicalObject::getWeight);
the Function<Car, ?> method ? apply(Car t) is adequately implemented by the Double getWeight() of superclass PhysicalObject, since t->getWeight() is a call to that method.
The PhysicalObject::getWeight method reference is like the following lambda:
Comparator<Car> c3_1 = comparing((Car t) -> {
PhysicalObject p = t;
return p.getWeight(); // call PhysicalObject::getWeight
});
Or the following anonymous class:
Comparator<Car> c3_1 = comparing(new Function<Car, Double>() {
@Override
public Double apply(Car t) {
PhysicalObject p = t;
return p.getWeight();
}
});
The widening conversion from Car to PhysicalObject is allowed in a method reference.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With