Kotlin Char比较失败

cha*_*nes 9 kotlin

我在Kotlin中有以下代码片段:

val pair: Pair<Char,Char> = 'z' to 'z'
val comparison = pair.first.compareTo(pair.second)
println(comparison)
Run Code Online (Sandbox Code Playgroud)

当我尝试运行它时,它在第二行失败并出现以下异常:

java.lang.ClassCastException:java.lang.Character无法强制转换为java.lang.Number

IDE(IntelliJ)不会抱怨任何错误的类型.这个问题在某种程度上与Chars来自的事实有关,Pair<Char, Char>因为'z'.compareTo('z')工作正常.你知道Kotlin如何解决以下的电话吗?

我正在使用Kotlin 1.0.4

hot*_*key 10

TL; DR显然,这是一个编译器错误.

这种行为的原因在于Kotlin编译器为这两个调用生成的字节码.(如果使用IntelliJ IDEA,则可以使用字节码查看工具检查字节).

首先,为'z'.compareTo('z')调用生成的字节码是:

LINENUMBER 10 L3
BIPUSH 122
BIPUSH 122
INVOKESTATIC kotlin/jvm/internal/Intrinsics.compare (II)I
Run Code Online (Sandbox Code Playgroud)

它调用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
Run Code Online (Sandbox Code Playgroud)

它也称之为kotlin.jvm.internal.Intrisics.compare,但这是它之前尝试做的事情:

  • 从对中获取组件(ALOAD 1INVOKEVIRTUAL ...线)
  • 检查对象是否可以强制转换为Number(CHECKCAST ...)
  • java.lang.Number.intValue()(INVOKEVIRTUAL ...)

第二和第三行是罪魁祸首,Char不是一个Number.它看起来像编译器为这种比较生成了不正确的字节码(这对于Number类型是正确的,似乎Char只是没有单独处理).

在Kotlin问题跟踪器中有一个问题,它可能会在未来版本中修复.


要暂时修复代码中的调用,可以Char在调用之前手动转换s:

pair.first.toInt().compareTo(pair.second.toInt())
Run Code Online (Sandbox Code Playgroud)