假设将Comparator.comparing源代码从

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));
}


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));
}

我们有以下 class
class PhysicalObject {
  double weight;
  public Double getWeight(){
    return weight;
  }
}
class Car extends PhysicalObject {}

以下状态无法编译
Function<PhysicalObject, Double> weight = p->p.getWeight();Comparator<Car> c = HypotheticComparators.comparing(weight);
而这个编译Comparator<Car> c3_1 = HypotheticComparators.comparing(PhysicalObject::getWeight);
我知道第一条语句无法编译是因为修改后的比较函数没有界通配符(? super T),但是为什么第二条语句可以编译却没有任何问题?

最佳答案

comparing定义为:

Comparator<T> comparing(Function<T, U> keyExtractor) // abbreviated

该声明:
Comparator<Car> c = comparing(weight);

需要将参数设为Function<Car, ?>,但weightFunction<PhysicalObject, Double>,因此会出现编译错误。

但是,当做
Comparator<Car> c3_1 = comparing(PhysicalObject::getWeight);
Function<Car, ?>方法? apply(Car t)由超类Double getWeight()PhysicalObject充分实现,因为t->getWeight()是对该方法的调用。
PhysicalObject::getWeight方法参考类似于以下lambda:
Comparator<Car> c3_1 = comparing((Car t) -> {
    PhysicalObject p = t;
    return p.getWeight(); // call PhysicalObject::getWeight
});

或以下匿名类:
Comparator<Car> c3_1 = comparing(new Function<Car, Double>() {
    @Override
    public Double apply(Car t) {
        PhysicalObject p = t;
        return p.getWeight();
    }
});

方法参考中允许从Car扩展到PhysicalObject

07-24 04:09