Skip to main content
ULong is an unsigned 64-bit integer type in Kotlin that represents values from 0 to 18,446,744,073,709,551,615 (26412^{64} - 1). It is implemented as a value class (specifically, a @JvmInline value class) that wraps a standard signed 64-bit Long. This design provides unsigned arithmetic and bitwise semantics while avoiding object allocation overhead at runtime, compiling down to a primitive long on the JVM in unboxed contexts.

Instantiation and Syntax

ULong literals are defined by appending the u (or U) and L suffixes to an integer literal.
Standard numeric types and strings can be explicitly converted to ULong using extension functions:

Memory Representation and Boxing

Because ULong is an inline value class, the Kotlin compiler treats it as a primitive long during execution whenever possible. However, boxing occurs when ULong is used in generic contexts, nullable types, or as an interface implementation.

Operations and Semantics

ULong supports standard arithmetic (+, -, *, /, %) and comparison (<, >, ==) operators. The Kotlin compiler translates these into unsigned operations at the bytecode level (e.g., utilizing java.lang.Long.divideUnsigned on the JVM).
Bitwise Operations: ULong supports standard bitwise operations (and, or, xor, inv). However, bitwise shift semantics differ from signed Long:
  • shr (Shift Right): Performs a logical shift (zero-fill), whereas shr on a signed Long performs an arithmetic shift (sign-extend).
  • ushr (Unsigned Shift Right): Not available on ULong, as shr already provides the logical shift behavior.
  • shl (Shift Left): Functions identically to signed integers.

ULongArray

To prevent boxing overhead when working with collections of ULong data, Kotlin provides ULongArray. At the JVM level, ULongArray is backed by a primitive long[], ensuring contiguous memory allocation and zero boxing per element.

Type Constraints and Interoperability

  • Widening Conversions: Kotlin does not implicitly widen types. A UInt cannot be passed to a function expecting a ULong without an explicit .toULong() cast.
  • Java Interoperability: Because Java lacks native unsigned types, ULong is exposed to Java code as a signed long. Functions accepting ULong in Kotlin will undergo name mangling in the generated JVM bytecode to prevent signature collisions with functions accepting signed Long.
Tired of Poor Kotlin Skills? Fix That With Deep Grasping!Learn More