TL; DR Najwyraźniej jest to błąd kompilatora.
Przyczyna tego zachowania leży w kodzie bajtowym generowanym przez kompilator Kotlin dla tych dwóch wywołań. (Jeśli używasz IntelliJ IDEA, możesz sprawdzić kod bajtowy za pomocą the bytecode viewing tool).
pierwsze, kod bajtowy generowane na wezwanie 'z'.compareTo('z')
jest:
LINENUMBER 10 L3
BIPUSH 122
BIPUSH 122
INVOKESTATIC kotlin/jvm/internal/Intrinsics.compare (II)I
Apeluje kotlin.jvm.internal.Intrisics.compare()
że porównuje dwa Int
s, a Char
s są wypychane do stosu bezpośrednio jako Int
s (BIPUSH
oznacza Push bajt jako liczba całkowita).
Ale jeśli spojrzeć na kod bajtowy dla pair.first.compareTo(pair.second)
znajdziesz coś takiego:
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
Apeluje kotlin.jvm.internal.Intrisics.compare
też, ale tutaj jest to, co próbuje zrobić przed:
- Get komponent z pary (linie
ALOAD 1
i INVOKEVIRTUAL ...
)
- Sprawdź, czy obiekt można obsadzić na
Number
(CHECKCAST ...
)
- Take
java.lang.Number.intValue()
(INVOKEVIRTUAL ...
)
Drugie i trzecie linie są winowajcą, Char
nie jest Number
. Po prostu wygląda na to, że kompilator wygenerował niepoprawny kod bajtowy dla tego porównania (byłoby to poprawne dla typów Number
, wydaje się, że Char
nie jest obsługiwane osobno).
Istnieje an issue about this w narzędziu do śledzenia zagadek Kotlin, prawdopodobnie zostanie on rozwiązany w przyszłych wydaniach.
Aby naprawić połączenie w kodzie teraz można przekonwertować Char
s ręcznie przed wywołaniem:
pair.first.toInt().compareTo(pair.second.toInt())