我在Kotlin中有以下代码片段:
val pair: Pair<Char,Char> = 'z' to 'z'
val comparison = pair.first.compareTo(pair.second)
println(comparison)
当我尝试运行它时,它在第二行失败并出现以下异常:
java.lang.ClassCastException:java.lang.Character无法强制转换为java.lang.Number
IDE(IntelliJ)并没有抱怨任何错误的类型。这个问题在某种程度上与Chars来自Pair<Char, Char>
的事实有关,因为'z'.compareTo('z')
工作正常。你知道Kotlin如何解决以下的电话吗?
我正在使用Kotlin 1.0.4
答案 0 :(得分:10)
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()
比较两个Int
,Char
被直接推送到堆栈Int
s 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
,但这是它之前尝试做的事情:
ALOAD 1
和INVOKEVIRTUAL ...
行)Number
(CHECKCAST ...
)java.lang.Number.intValue()
(INVOKEVIRTUAL ...
)第二行和第三行是罪魁祸首,Char
不是Number
。看起来编译器为这种比较生成了不正确的字节码(对Number
类型来说是正确的,似乎Char
不是单独处理的。)
Kotlin问题跟踪器中有an issue about this,可能会在将来的版本中修复。
要暂时修复您的代码中的通话,您可以在通话前手动转换Char
:
pair.first.toInt().compareTo(pair.second.toInt())