Котлин чар сравнениедля не

у меня есть следующий фрагмент кода в Котлин:

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

он терпит неудачу во второй строке со следующим исключением, когда я пытаюсь запустить его:

java.ленг.ClassCastException: java.ленг.Символ не может быть приведен к java.ленг.Номер

IDE (IntelliJ) не жалуется на неправильный тип. Проблема как-то связана с тем, что символы исходят от Pair<Char, Char>, потому что 'z'.compareTo('z') работает нормально. Знаете ли вы, как Котлин решает после звонка?

Я использую Kotlin 1.0.4

1 ответов


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С толкнул в стек прямо как Ints (BIPUSH означает push byte как целое число).

но если вы посмотрите на байт-код для 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 он, вероятно, будет исправлен в будущих выпусках.


To исправьте вызов в своем коде сейчас, вы можете преобразовать Chars вручную перед вызовом:

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