Beberapa domain data hanya mengandung nilai non-negatif: ukuran file, ID database, port jaringan, dan bit mask. Untuk kasus ini, Kotlin menyediakan empat tipe integer unsigned: UByte, UShort, UInt, dan ULong. Tipe-tipe ini memperluas rentang positif dari padanan signed-nya tanpa menambah ukuran memori. Pada chapter ini kita akan membedah deklarasi, rentang, suffix literal, serta kapan memakai tipe unsigned dan kapan menghindarinya.
Empat tipe unsigned #
| Tipe | Lebar | Rentang | Padanan signed |
|---|---|---|---|
UByte | 8 bit | 0 .. 255 | Byte (-128 .. 127) |
UShort | 16 bit | 0 .. 65.535 | Short |
UInt | 32 bit | 0 .. 4.294.967.295 | Int |
ULong | 64 bit | 0 .. 18.446.744.073.709.551.615 | Long |
Memori yang digunakan sama dengan padanan signed — UByte tetap 1 byte, ULong tetap 8 byte. Perbedaannya hanya pada interpretasi bit (ada bit tanda atau tidak).
Literal dan suffix #
Literal unsigned menggunakan suffix u atau U:
val a: UByte = 200u
val b: UShort = 60_000u
val c: UInt = 4_000_000_000u
val d: ULong = 18_000_000_000_000_000_000uAturan inferensi tipe unsigned:
42utanpa tipe eksplisit disimpulkan sebagaiUIntjika muat, atauULongjika melampauiUInt.MAX_VALUE.- Untuk memaksakan
ULongwalaupun nilai kecil, gunakan42uLatau42UL. - Tipe eksplisit (
val x: UByte = 200u) memaksa literal ditafsirkan sebagai tipe tersebut.
Use case tipe unsigned #
Beberapa domain yang cocok memakai tipe unsigned:
| Use case | Tipe yang disarankan | Alasan |
|---|---|---|
| Ukuran file dalam byte | ULong | Bisa melampaui Long.MAX_VALUE untuk file besar |
| Port jaringan (0-65535) | UShort | Port tidak pernah negatif |
| Komponen warna RGB (0-255) | UByte | Range tepat 0..255 |
| ID database di atas 2^31 | UInt atau ULong | Menghindari overflow yang tidak perlu |
| Bit mask / flag | UInt atau ULong | Operasi bit lebih intuitif tanpa tanda |
Demonstrasi unsigned #
Berikut program lengkap yang memperlihatkan deklarasi, rentang, use case, dan operasi bit:
fun main() {
val uByte: UByte = 200u
val uShort: UShort = 60_000u
val uInt: UInt = 4_000_000_000u
val uLong: ULong = 18_000_000_000_000_000_000u
println("uByte = $uByte (size ${UByte.SIZE_BITS} bit)")
println("uShort = $uShort (size ${UShort.SIZE_BITS} bit)")
println("uInt = $uInt")
println("uLong = $uLong")
println()
println("Range tipe unsigned:")
println("UByte : ${UByte.MIN_VALUE} .. ${UByte.MAX_VALUE}")
println("UShort : ${UShort.MIN_VALUE} .. ${UShort.MAX_VALUE}")
println("UInt : ${UInt.MIN_VALUE} .. ${UInt.MAX_VALUE}")
println("ULong : ${ULong.MIN_VALUE} .. ${ULong.MAX_VALUE}")
println()
val ukuranFileByte: ULong = 5_000_000_000u
println("Ukuran file (byte) = $ukuranFileByte")
println("Konversi ke MB = ${ukuranFileByte / 1_048_576u} MB (1_048_576 byte = 1 MB)")
println()
val maskUByte: UByte = 0xFFu
val flagA: UByte = 0b0000_1010u
val flagB: UByte = 0b0001_0100u
val kombinasi = flagA or flagB
println("maskUByte = $maskUByte")
println("flagA (0b0000_1010) = ${flagA.toString(2).padStart(8, '0')}")
println("flagB (0b0001_0100) = ${flagB.toString(2).padStart(8, '0')}")
println("flagA or flagB = ${kombinasi.toString(2).padStart(8, '0')}")
println()
val a: UInt = 42u
val b = a.toInt()
println("a (UInt) = $a -> toInt() = $b (${b.javaClass.simpleName})")
println()
val maxInt = Int.MAX_VALUE.toUInt()
val tambah = maxInt + 1u
println("Int.MAX_VALUE.toUInt() = $maxInt")
println("tambah 1u = $tambah (tidak overflow karena unsigned)")
}Output yang Dihasilkan:
uByte = 200 (size 8 bit)
uShort = 60000 (size 16 bit)
uInt = 4000000000
uLong = 18000000000000000000
Range tipe unsigned:
UByte : 0 .. 255
UShort : 0 .. 65535
UInt : 0 .. 4294967295
ULong : 0 .. 18446744073709551615
Ukuran file (byte) = 5000000000
Konversi ke MB = 4768 MB (1_048_576 byte = 1 MB)
maskUByte = 255
flagA (0b0000_1010) = 00001010
flagB (0b0001_0100) = 00010100
flagA or flagB = 00011110
a (UInt) = 42 -> toInt() = 42 (int)
Int.MAX_VALUE.toUInt() = 2147483647
tambah 1u = 2147483648 (tidak overflow karena unsigned)Mari kita amati baris-baris penting pada kode di atas:
- Baris 2-5 — deklarasi dengan tipe eksplisit. Suffix
uwajib agar literal ditafsirkan sebagai unsigned; tanpa suffix,200akan menjadiInt(dan gagal karena di luar rangeBytesigned). - Baris 13-16 (
MIN_VALUE,MAX_VALUE) —MIN_VALUEuntuk semua tipe unsigned adalah0.MAX_VALUEadalah2^N - 1. - Baris 19 (
ukuranFileByte / 1_048_576u) — pembagian unsigned wajib literal unsigned (1_048_576u). Hasilnya 4768 MB, yang akurat untuk 5 GB. - Baris 25 (
flagA or flagB) — operatoror(bisa juga infix) melakukan operasi bitwise OR. Hasil0b0000_1010 or 0b0001_0100 = 0b0001_1110. Method.toString(2).padStart(8, '0')memformat sebagai biner 8-bit. - Baris 31-32 (
a.toInt()) — konversi eksplisitUInt → Int. Bila nilai melampauiInt.MAX_VALUE, hasil akan ter-wrap-around ke nilai negatif — tidak ada exception. - Baris 35-36 (
Int.MAX_VALUE.toUInt() + 1u) — konversiInt → UIntlalu penambahan. Hasil2.147.483.648— tidak overflow karenaUInt.MAX_VALUEadalah4.294.967.295. Ini menunjukkan keuntungan utama unsigned.
Operasi bitwise #
Tipe unsigned mendukung operasi bitwise yang sama dengan signed:
| Operator | Nama | Contoh |
|---|---|---|
or | OR bitwise | 0b1010u or 0b0101u |
and | AND bitwise | 0b1110u and 0b1011u |
xor | XOR bitwise | 0b1010u xor 0b0011u |
inv() | NOT bitwise (inversi) | 0b00001111u.inv() |
shl(bits) | Shift left | 1u shl 4 |
shr(bits) | Shift right logical | 0b10000000u shr 4 |
Konversi signed ↔ unsigned #
Konversi antara signed dan unsigned bersifat eksplisit — kompilator tidak melakukan konversi implisit. Method yang tersedia: .toUByte(), .toUShort(), .toUInt(), .toULong(), dan sebaliknya .toByte(), .toShort(), .toInt(), .toLong().
val signed: Int = -1
val unsigned: UInt = signed.toUInt() // 4294967295 (semua bit 1)
val kembali: Int = unsigned.toInt() // -1 (kembali ke nilai asli)Referensi Lanjutan #
- Unsigned integers
— dokumentasi resmi tipe unsigned Kotlin
UByte,UShort,UInt, danULong - Numbers — rujukan tipe angka Kotlin sebagai pembanding untuk representasi signed vs unsigned
Pemilihan tipe unsigned bergantung pada konteks data. Berikutnya, kita akan melihat tipe-tipe khusus Kotlin yang berperan sebagai akar hierarki tipe — Any, Unit, dan Nothing — pada chapter Any, Unit, dan Nothing.