我在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()
比较两个Int
s,Char
s被直接推送到堆栈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
Run Code Online (Sandbox Code Playgroud)
它也称之为kotlin.jvm.internal.Intrisics.compare
,但这是它之前尝试做的事情:
ALOAD 1
和INVOKEVIRTUAL ...
线)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)
归档时间: |
|
查看次数: |
332 次 |
最近记录: |