Unsigned integer types
In addition to integer types, Kotlin provides the following types for unsigned integer numbers:
UByte: an unsigned 8-bit integer, ranges from 0 to 255
UShort: an unsigned 16-bit integer, ranges from 0 to 65535
UInt: an unsigned 32-bit integer, ranges from 0 to 2^32 - 1
ULong: an unsigned 64-bit integer, ranges from 0 to 2^64 - 1
Unsigned types support most of the operations of their signed counterparts.
Unsigned arrays and ranges
Same as for primitives, each of unsigned type has corresponding type that represents arrays of that type:
UByteArray: an array of unsigned bytes
UShortArray: an array of unsigned shorts
UIntArray: an array of unsigned ints
ULongArray: an array of unsigned longs
Same as for signed integer arrays, they provide similar API to
Array class without boxing overhead.
When you use unsigned arrays, you'll get a warning that indicates that this feature is not stable yet. To remove the warning, opt-in the
@ExperimentalUnsignedTypes annotation. It's up to you to decide if your clients have to explicitly opt-in into usage of your API, but keep in mind that unsigned arrays are not a stable feature, so API which uses them can be broken by changes in the language. Learn more about opt-in requirements.
Ranges and progressions are supported for
ULong by classes
ULongProgression. Together with the unsigned integer types, these classes are stable.
Unsigned integers literals
To make unsigned integers easier to use, Kotlin provides an ability to tag an integer literal with a suffix indicating a specific unsigned type (similarly to
Utag is for unsigned literals. The exact type is determined based on the expected type. If no expected type is provided, compiler will use
ULongdepending on the size of literal:val b: UByte = 1u // UByte, expected type provided val s: UShort = 1u // UShort, expected type provided val l: ULong = 1u // ULong, expected type provided val a1 = 42u // UInt: no expected type provided, constant fits in UInt val a2 = 0xFFFF_FFFF_FFFFu // ULong: no expected type provided, constant doesn't fit in UInt
ULexplicitly tag literal as unsigned long:val a = 1UL // ULong, even though no expected type provided and constant fits into UInt
The main use case of unsigned numbers is utilizing the full bit range of an integer to represent positive values.
For example, to represent hexadecimal constants that do not fit in signed types such as color in 32-bit
You can use unsigned numbers to initialize byte arrays without explicit
toByte() literal casts:
Another use case is interoperability with native APIs. Kotlin allows representing native declarations that contain unsigned types in the signature. The mapping won't substitute unsigned integers with signed ones keeping the semantics unaltered.
While unsigned integers can only represent positive numbers and zero, it's not a goal to use them where application domain requires non-negative integers. For example, as a type of collection size or collection index value.
There are a couple of reasons:
Using signed integers can help to detect accidental overflows and signal error conditions, such as
List.lastIndexbeing -1 for an empty list.
Unsigned integers cannot be treated as a range-limited version of signed ones because their range of values is not a subset of the signed integers range. Neither signed, nor unsigned integers are subtypes of each other.