TL;DR显然,这是一个编译器错误。
这种行为的原因在于 Kotlin 编译器为这两个调用生成的字节码。 (如果您使用 IntelliJ IDEA,您可以使用 the bytecode viewing tool 检查字节码)。
首先,为'z'.compareTo('z')调用生成的字节码是:
LINENUMBER 10 L3
BIPUSH 122
BIPUSH 122
INVOKESTATIC kotlin/jvm/internal/Intrinsics.compare (II)I
它调用kotlin.jvm.internal.Intrisics.compare() 比较两个Ints,Chars 直接作为Ints 推入堆栈(BIPUSH 表示将字节推入整数) .
但是如果您查看pair.first.compareTo(pair.second) 的字节码,您会发现如下内容:
ALOAD 1
INVOKEVIRTUAL kotlin/Pair.getFirst ()Ljava/lang/Object;
CHECKCAST java/lang/Number
INVOKEVIRTUAL java/lang/Number.intValue ()I
ALOAD 1
INVOKEVIRTUAL kotlin/Pair.getSecond ()Ljava/lang/Object;
CHECKCAST java/lang/Number
INVOKEVIRTUAL java/lang/Number.intValue ()I
INVOKESTATIC kotlin/jvm/internal/Intrinsics.compare (II)I
它也调用kotlin.jvm.internal.Intrisics.compare,但这是它之前尝试做的事情:
第二行和第三行是罪魁祸首,Char 不是Number。看起来编译器为此比较生成了不正确的字节码(对于 Number 类型是正确的,似乎 Char 只是没有单独处理)。
在 Kotlin 问题跟踪器中有 an issue about this,它可能会在未来的版本中得到修复。
要暂时修复代码中的调用,您可以在调用之前手动转换Chars:
pair.first.toInt().compareTo(pair.second.toInt())