Kotlin Char compareTo失败

我在Kotlin中有下面的代码片段:

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

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

 java.lang.ClassCastException: java.lang.Character cannot be cast to java.lang.Number 

IDE(IntelliJ)不会抱怨任何错误的类型。 这个问题与Chars来自Pair<Char, Char>因为'z'.compareTo('z')工作正常。 你知道科特林如何解决以下的电话?

我正在使用Kotlin 1.0.4

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

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

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

 LINENUMBER 10 L3 BIPUSH 122 BIPUSH 122 INVOKESTATIC kotlin/jvm/internal/Intrinsics.compare (II)I 

它调用kotlin.jvm.internal.Intrisics.compare()比较两个Int ,并将Char直接作为IntBIPUSH表示push字节作为整数 )推送到堆栈。

但是,如果您查看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 ,但是这是它之前尝试做的事情:

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

第二和第三行是罪魁祸首, Char不是Number 。 它看起来就像编译器为这个比较生成了不正确的字节码(对于Number类型来说是正确的,好像Char只是不能单独处理)。

在Kotlin问题跟踪器中存在一个问题 ,在将来的版本中它可能会被修复。


为了立即修复您的代码中的通话,您可以在通话之前手动转换Char

 pair.first.toInt().compareTo(pair.second.toInt())