[英]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)
由超类PhysicalObject
的Double 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. 在方法引用中允许从
Car
到PhysicalObject
的扩展转换。
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.