Kotlin字符串解析时如何判断整数溢出及自动匹配类型?
针对Kotlin MPP的整数溢出判断方案
现有库情况
目前没有专门面向Kotlin多平台项目的通用整数溢出判断库,不过可以基于Kotlin标准库实现成熟的判断逻辑,覆盖有符号和无符号整数类型。
核心判断算法
1. 有符号整数类型(Byte/Short/Int/Long)
利用kotlin.math.BigInteger做范围校验,它能处理任意大小的整数,不会触发溢出:
import kotlin.math.BigInteger fun String.canFitIntoByte(): Boolean { val bigInt = BigInteger(this) return bigInt >= BigInteger.valueOf(Byte.MIN_VALUE.toLong()) && bigInt <= BigInteger.valueOf(Byte.MAX_VALUE.toLong()) } fun String.canFitIntoShort(): Boolean { val bigInt = BigInteger(this) return bigInt >= BigInteger.valueOf(Short.MIN_VALUE.toLong()) && bigInt <= BigInteger.valueOf(Short.MAX_VALUE.toLong()) } fun String.canFitIntoInt(): Boolean { val bigInt = BigInteger(this) return bigInt >= BigInteger.valueOf(Int.MIN_VALUE.toLong()) && bigInt <= BigInteger.valueOf(Int.MAX_VALUE.toLong()) } fun String.canFitIntoLong(): Boolean { return try { this.toLong() true } catch (e: NumberFormatException) { false } }
2. 无符号整数类型(UByte/UShort/UInt/ULong)
无符号整数最小值为0,仅需判断是否超过对应类型的最大值:
fun String.canFitIntoUByte(): Boolean { val bigInt = BigInteger(this) return bigInt >= BigInteger.ZERO && bigInt <= BigInteger.valueOf(UByte.MAX_VALUE.toLong()) } fun String.canFitIntoUShort(): Boolean { val bigInt = BigInteger(this) return bigInt >= BigInteger.ZERO && bigInt <= BigInteger.valueOf(UShort.MAX_VALUE.toLong()) } fun String.canFitIntoUInt(): Boolean { val bigInt = BigInteger(this) return bigInt >= BigInteger.ZERO && bigInt <= BigInteger.valueOf(UInt.MAX_VALUE.toLong()) } fun String.canFitIntoULong(): Boolean { return try { this.toULong() true } catch (e: NumberFormatException) { false } }
3. 自动匹配最合适的整数类型
如果需要从字符串自动推断最小能容纳的类型,可按范围从小到大依次校验:
sealed class IntegerType { object Byte : IntegerType() object Short : IntegerType() object Int : IntegerType() object Long : IntegerType() object UByte : IntegerType() object UShort : IntegerType() object UInt : IntegerType() object ULong : IntegerType() object Invalid : IntegerType() } fun String.inferIntegerType(isUnsigned: Boolean = false): IntegerType { return if (isUnsigned) { when { canFitIntoUByte() -> IntegerType.UByte canFitIntoUShort() -> IntegerType.UShort canFitIntoUInt() -> IntegerType.UInt canFitIntoULong() -> IntegerType.ULong else -> IntegerType.Invalid } } else { when { canFitIntoByte() -> IntegerType.Byte canFitIntoShort() -> IntegerType.Short canFitIntoInt() -> IntegerType.Int canFitIntoLong() -> IntegerType.Long else -> IntegerType.Invalid } } }
注意事项
- 无符号类型直接判定负数为无效,因为无符号整数不支持负数值。
- 超大数字字符串的处理中,
BigInteger的性能足以满足TOML反序列化场景需求。 - 反序列化时需先校验输入字符串是否为合法整数(含正负号、无符号标识),再执行范围判断。
内容的提问来源于stack exchange,提问作者Andrew Kuleshov
相关产品推荐
相关产品推荐

