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
直接作为Int
( BIPUSH
表示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 1
和INVOKEVIRTUAL ...
行) - 检查对象是否可以转换为
Number
(CHECKCAST ...
) - 取
java.lang.Number.intValue()
(INVOKEVIRTUAL ...
)
第二和第三行是罪魁祸首, Char
不是Number
。 它看起来就像编译器为这个比较生成了不正确的字节码(对于Number
类型来说是正确的,好像Char
只是不能单独处理)。
在Kotlin问题跟踪器中存在一个问题 ,在将来的版本中它可能会被修复。
为了立即修复您的代码中的通话,您可以在通话之前手动转换Char
:
pair.first.toInt().compareTo(pair.second.toInt())