Scala 解决 Comparator.thenComparing 中的错误覆盖

标签 scala generics scala-java-interop

我正在尝试翻译以下 Java 代码:

import java.util.Comparator;

public class ComparatorTestJava {
    public static void test() {
        Comparator<String> cmp = (s1, s2) -> 0;
        cmp = cmp.thenComparing(s -> s);
    }
}

进入斯卡拉。我认为这应该有效:

import java.util.{Comparator, function}

object ComparatorTest {
  var comparator: Comparator[String] = (t1, t2) ⇒ 0
  comparator = comparator.thenComparing(new function.Function[String, String] {
    override def apply(t: String): String = t
  })
}

但它失败并出现以下错误:
Error:(7, 41) type mismatch;
 found   : java.util.function.Function[String,String]
 required: java.util.Comparator[? >: String]
  comparator = comparator.thenComparing(new function.Function[String, String] {

看起来 Scala 编译器确信我正在尝试使用 thenComparing(Comparator)而不是 thenComparing(Function) .有什么办法可以告诉它是什么吗?或者这实际上不是问题?

(我意识到还有其他可能更惯用的方法来在 Scala 中构建比较器,但我有兴趣了解为什么会失败。)

最佳答案

鉴于定义

val comparator: Comparator[String] = (t1, t2) => 0
val f: function.Function[String, String] = s => s

以下失败并出现与您的问题相同的错误:
comparator.thenComparing(f)

但这编译成功:
comparator.thenComparing[String](f)

这是一种非常常见的错误类型,每当尝试使用 Scala 的通用 Java 接口(interface)时都会经常发生。原因是 Java 的使用点变化与 Scala 的声明点变化不能很好地配合,所以 Java 的 Comparator<? super T>转换为通配符类型Comparator[_ >: T] ,并且它以某种方式混淆了类型推断算法(特别是如果将它与重载方法和 SAM 结合使用)。但是,一旦识别出来,通过显式指定类型参数很容易解决问题,在这种情况下,添加显式 [String]足够。

关于Scala 解决 Comparator.thenComparing 中的错误覆盖,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54609769/

相关文章:

scala - Lightbend Lagom 和 Akka : Unable to hit rest endpoint of lagom services

javascript - 在 AngularJS $scope 中访问 Play Scala 变量

java - 不存在类型变量 U 的实例,因此 Row 符合 Iterable<?延伸 U>

java - 将 java.lang.String 转换为 Scala 字符串

java - 包含原语的 Scala 集合的安全转换

class - Scala 中的主要方法

java - Spring + Scala + 匿名 block 或类

c# - 关于泛型类型的澄清

c# - C# 中的泛型,Dictionary<TKey,TValue>

scala - 将 Scala Set 转换为 Java (java.util.Set)?