TL; DR вы можете создать пользовательскую функцию расширения, которая проверяет, находится ли значение между Int.MIN_VALUE и Int.MAX_VALUE
fun Long.toIntThrowing() : Int {
if (this < Int.MIN_VALUE || this > Int.MAX_VALUE) {
throw RuntimeException()
}
return this.toInt()
}
Наблюдается "странное" поведение, которое вы наблюдаете, потому что в Kotlin, Long представляется как 64-битное целое число со знаком, а Int представляется как 32-битное целое число со знаком.
В то время как 123L легко представляется 32-битным целым числом, Long.MAX_VALUE переполняет Integer (почти) дважды, в результате чего вы наблюдаете поведение.
Я полагаю, что приведенный ниже пример лучше иллюстрирует это:
println((2147483647L).toInt()) // the max 32 bit signed int
println((2147483648L).toInt()) // 1 more overflows it to the min (negative) 32 bit signed int
println((2147483649L).toInt()) // 2 more...
println((Long.MAX_VALUE - 1).toInt())
println((Long.MAX_VALUE).toInt())
приводит к:
2147483647
-2147483648
-2147483647
-2
-1
От: https://discuss.kotlinlang.org/t/checked-and-unsigned-integer-operations/529/2
Исключения при арифметическом переполнении: это, вероятно, значительно замедлит арифметику, и мы не видим, как ее избежать без изменений в JVM, и мы не готовы принять замедление