Eclipse或Javac bug; lambda类型推断

时间:2017-02-08 12:51:01

标签: java eclipse lambda language-lawyer

以下代码使用 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错误报告的链接。

1 个答案:

答案 0 :(得分:2)

你的解释没有实现。 Comparator.comparing(...)(单个参数版本)的参数不应该是Comparable<T>,而是Function<? super T,? extends U>,而T := AUU 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,但显然,由于Integerint所需的装箱,这个特定的Eclipse版本无法执行此操作。 / p>

作为旁注,当您想要比较Integer属性时,您可能还想使用int。使用此工厂,返回的比较器可以完全避免将Comparator.comparingInt(...)装入int

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

正确的习语是

int

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