java - Eclipse 或 Javac 错误; lambda 类型推断

标签 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<? super 可比>.

我认为 Comparator.comparing(...) 的论点应该是Comparable<T>T = A ,使用函数方法 compareTo返回 int 。 Eclipse 似乎认为 lambda 函数应该返回 Comparable>

我强烈怀疑 Eclipse 存在 bug,但是在某些情况下 Eclipse 已经正确实现了语言规范,而 javac 没有,所以似乎值得问:这是 Eclipse bug 还是 < em>javac 错误?任何语言律师都可以指出语言规范的相关部分吗?

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

Java 8 Stream flatMap and group by code compiler error - 类似的错误消息,但不清楚是否是完全相同的问题; Answer 声称这是一个 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 错误报告的链接。

最佳答案

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

所以当你说

Eclipse seems to believe that the lambda function should return Comparable<? super Comparable<? super U>>

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

但是你的函数返回 int应该比较的值,当您将该值框到 Integer 时,您有一个满足预期 U extends Comparable<? super U> 的类型约束,如Integer实现Comparable<Integer> 。换句话说,U应该推断为Integer ,但显然,这个特定的 Eclipse 版本由于需要装箱 int 而无法执行此操作。至Integer .


作为旁注,当您想要比较int时属性,您可能需要使用 Comparator.comparingInt(...)反正。通过这个工厂,返回的比较器避免了 int 的装箱。至Integer总共。

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

正确的习惯用法是

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

其工作原理是交换两个元素进行比较,这在所有场景下都有效,并且没有性能缺陷。

关于java - Eclipse 或 Javac 错误; lambda 类型推断,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42113629/

相关文章:

java - 如何从 JSONObject 中检索日期

java - Websphere 中的 Eclipse Scout RAP UI 部署

java - 我应该关闭哪些编译器警告?

java - JavaFX 中使用 Lambda 表达式的键绑定(bind)不起作用

java - JasperReports 是在 Web 应用程序中显示报告的适当解决方案吗?

java - Window注册表创建 key 在java中不起作用

node.js - 如何替换输出 lambda 函数 url 中的 'latest'?我怎样才能制作自己的资源?

lambda - Java 8 - 如何使用流收集器对 map 列表进行分组和求和

Java servlet - session 清理 (HttpServletRequest)

java - 自动生成标题