Eclipse或Javac错误;lambda类型推断



以下代码使用javac和Eclipse 4.6.1/4.6进行编译,但在Eclipse 4.6.2:中产生错误

package ecbug;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class Foo
{
class A
{
public int getStart() { return 0; }
}
void someMethod(List<A> toRemove)
{
Collections.sort(toRemove, Comparator.comparing(t -> -t.getStart()));
}
}

Eclipse 4.6.2在-t.getStart()下抱怨存在类型不匹配:无法从int转换为Comparable<?超级可比<?超级U>gt

我认为Comparator.comparing(...)的自变量应该是Comparable<T>T = A,函数方法compareTo返回int。Eclipse似乎认为lambda函数应该返回Comparable<?超级可比<?超级U>gt

我强烈怀疑是Eclipse错误,但在某些情况下,Eclipse确实正确地实现了语言规范,而javac没有,所以似乎值得一问:这是Eclipse错误还是javacbug?有语言律师能指出语言规范的相关部分吗?

可能相关的问题,在我看来不是重复的:

Java 8流flatMap和group-by-code编译器错误-类似的错误消息,但不清楚是否是完全相同的问题;Answer声称这是一个Eclipse错误,但没有提供错误链接,也没有JLS报价;指的是旧的Eclipse版本。

为什么没有';这个java 8示例使用类型推理在Eclipse中编译吗?-类似于以前的

flatMap返回List<对象>而不是List<字符串>-同样,这可能是一个不同的问题;注释声明了Eclipse问题,但并没有通过引用JLS来证明,也没有提供到Eclipse错误报告的链接。

您的解释不符合要求。Comparator.comparing(...)(单参数版本)的参数不应该是Comparable<T>,而是Function<? super T,? extends U>,而T := A,但UU extends Comparable<? super U>

所以当你说

Eclipse似乎认为lambda函数应该返回Comparable<? super Comparable<? super U>>

您对Eclipse的期望是正确的,Eclipse对此也抱有正确的期望。

但是您的函数返回一个应该进行比较的int值,当您将该值框入Integer时,您就得到了一个满足预期U extends Comparable<? super U>约束的类型,因为Integer实现了Comparable<Integer>。换句话说,U应该被推断为Integer,但显然,由于intInteger需要装箱,这个特定的Eclipse版本无法做到这一点。


附带说明一下,当您想要比较int属性时,您可能无论如何都要使用Comparator.comparingInt(...)。使用此工厂,返回的比较器完全避免了intInteger的装箱。

此外,不应通过求反来反转整数排序。问题是
-Integer.MIN_VALUE == Integer.MIN_VALUE,因为试图否定最小可能的int值会导致溢出,再次评估最小的int值,而不是最大的值。使用否定来反转订单可能在很多情况下都有效,在其中一些情况下,它可能是合理的,因为可以排除这种特殊值,然而,它会产生一种坏习惯,在这种情况下可能会适得其反,当然,这种情况很少发生,通常只发生在客户身上…

正确的习语应该是

Collections.sort(toRemove, Comparator.comparingInt(A::getStart).reversed());

它通过交换两个元素来进行比较,这在所有场景中都是有效的,并且没有性能缺陷。

最新更新