简体   繁体   English

比较器比较类型推断

[英]Comparator comparing type inference

Let's say change Comparator.comparing source code from 让我们说改变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));
}

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 以下statament无法编译

Function<PhysicalObject, Double> weight = p->p.getWeight();

Comparator<Car> c = HypotheticComparators.comparing(weight);

while this compile Comparator<Car> c3_1 = HypotheticComparators.comparing(PhysicalObject::getWeight); 而这个编译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 ? 据我所知,第一个语句无法编译是因为修改后的比较函数没有有界通配符( ? super T ),但为什么第二个语句可以编译而没有任何问题?

With comparing defined as: comparing定义为:

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. 要求参数是一个Function<Car, ?> ,但weight是一个Function<PhysicalObject, Double>所以你得到了编译错误。

However, when doing 但是,在做的时候

Comparator<Car> c3_1 = comparing(PhysicalObject::getWeight);

the Function<Car, ?> method ? apply(Car t) Function<Car, ?>方法? apply(Car t) ? apply(Car t) is adequately implemented by the Double getWeight() of superclass PhysicalObject , since t->getWeight() is a call to that method. ? apply(Car t)由超类PhysicalObjectDouble getWeight()充分实现,因为t->getWeight()是对该方法的调用。

The PhysicalObject::getWeight method reference is like the following lambda: PhysicalObject::getWeight方法引用类似于以下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. 在方法引用中允许从CarPhysicalObject的扩展转换。

According to the JLS ( §18.2.1: Expression Compatibility Constraints ), this is due to the Reduction stage for exact method references within the chapter on Type Inference, as seen by the image below. 根据JLS(第18.2.1节:表达式兼容性约束 ),这是由于类型推理章节中精确方法参考的缩减阶段,如下图所示。

在此输入图像描述

Essentially, the compiler is able to infer that, because Car extends PhysicalObject , it should be able to define a Comparator<Car> with a Function<Car, Double> . 本质上,编译器能够推断出,因为Car扩展了PhysicalObject ,它应该能够使用Function<Car, Double>定义Comparator<Car> Function<Car, Double>

Explicitly passing a Function<PhysicalObject, Double> to create a Comparator<Car> will not work though, as there is not enough information available for the compiler to properly infer it. 显式传递Function<PhysicalObject, Double>以创建Comparator<Car>将无法正常工作,因为没有足够的信息可供编译器正确推断。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM