以下代码使用 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&lt;?超级可比&lt;?超级U&gt;&gt; 。
我认为Comparator.comparing(...)
的参数应为Comparable<T>
T = A
,功能方法compareTo返回int
。 Eclipse似乎相信lambda函数应该返回 Comparable&lt;?超级可比&lt;?然而,超级U&gt;&gt; 。
我强烈怀疑是一个Eclipse错误,但是肯定有Eclipse正确实现了语言规范并且 javac 没有的情况,所以似乎值得一提:这是一个Eclipse bug还是< em> javac bug?任何语言律师都可以指出语言规范的相关部分吗?
可能相关的问题,在我看来并不重复:
Java 8 Stream flatMap and group by code compiler error - 类似的错误消息,但不清楚它是否完全相同;回答声称它是一个Eclipse bug,但没有提供bug链接和JLS引用;指的是旧的Eclipse版本。
Why didn't this java 8 example using type inference compile in Eclipse? - 与之前的相似
Java Stream collect after flatMap returns List<Object> instead of List<String> - 再次,可能是一个不同的问题;注释声称Eclipse存在问题,但不能通过引用JLS来证明,也不提供Eclipse错误报告的链接。
答案 0 :(得分:2)
你的解释没有实现。 Comparator.comparing(...)
(单个参数版本)的参数不应该是Comparable<T>
,而是Function<? super T,? extends U>
,而T := A
,U
为U extends Comparable<? super U>
}。
所以当你说
时Eclipse似乎相信lambda函数应该返回
Comparable<? super Comparable<? super U>>
你对Eclipse的期望是正确的,Eclipse也是正确的期望。
但是你的函数返回一个应该被比较的int
值,当你将该值设置为Integer
时,你有一个满足预期U extends Comparable<? super U>
约束的类型,为{ {1}}实施Integer
。换句话说,Comparable<Integer>
应该被推断为U
,但显然,由于Integer
到int
所需的装箱,这个特定的Eclipse版本无法执行此操作。 / p>
作为旁注,当您想要比较Integer
属性时,您可能还想使用int
。使用此工厂,返回的比较器可以完全避免将Comparator.comparingInt(...)
装入int
。
此外,您不应该通过否定来反转整数排序。问题在于
Integer
,因为尝试否定最小可能-Integer.MIN_VALUE == Integer.MIN_VALUE
值会导致溢出再次评估为最小int
值,而不是最大值。使用否定来反转顺序可能在很多情况下都有效,在某些情况下它可能是合理的,因为这个特殊值可以被排除,然而,它会产生一个坏习惯,在可能发生这种情况的情况下可能适得其反当然,很少,通常只在客户处......
正确的习语是
int
通过交换两个要比较的元素来工作,这在所有场景中都是有效的,并且没有性能缺陷。