【问题标题】:Kotlin Char compareTo failsKotlin Char compareTo 失败
【发布时间】:2017-04-19 04:12:37
【问题描述】:

我在 Kotlin 中有以下代码 sn-p:

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&lt;Char, Char&gt; 的事实有关,因为 'z'.compareTo('z') 工作正常。你知道 Kotlin 是如何解决以下调用的吗?

我使用的是 Kotlin 1.0.4

【问题讨论】:

    标签: kotlin


    【解决方案1】:

    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() 比较两个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
    

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

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

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

    在 Kotlin 问题跟踪器中有 an issue about this,它可能会在未来的版本中得到修复。


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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-08-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-08-21
      相关资源
      最近更新 更多