Bilangan bulat adalah tipe data paling sering dipakai dalam program. Kotlin menyediakan empat tipe integer signed: Byte, Short, Int, dan Long, masing-masing dengan lebar bit 8, 16, 32, dan 64. Selain itu, Kotlin juga menyediakan tipe unsigned (UByte, UShort, UInt, ULong) untuk kasus ketika kita tahu nilai tidak pernah negatif. Pada chapter ini kita akan membedah rentang masing-masing tipe, perilaku overflow yang melingkari batas, serta perkenalan singkat tipe unsigned.
Empat tipe integer signed #
Setiap tipe integer signed memiliki rentang simetris di sekitar nol:
| Tipe | Lebar | Rentang | Memori |
|---|---|---|---|
Byte | 8 bit | -128 .. 127 | 1 byte |
Short | 16 bit | -32.768 .. 32.767 | 2 byte |
Int | 32 bit | -2.147.483.648 .. 2.147.483.647 | 4 byte |
Long | 64 bit | -9.223.372.036.854.775.808 .. 9.223.372.036.854.775.807 | 8 byte |
Int adalah tipe default untuk bilangan bulat literal. Saat kita menulis 42, kompilator menyimpulkan Int. Untuk Long, gunakan suffix L (misalnya 42L).
Demonstrasi tipe dan rentang #
Berikut program yang memperlihatkan rentang dan contoh penggunaan setiap tipe:
fun main() {
println("Range tipe integer:")
println("Byte : ${Byte.MIN_VALUE} .. ${Byte.MAX_VALUE} (${Byte.SIZE_BITS} bit)")
println("Short : ${Short.MIN_VALUE} .. ${Short.MAX_VALUE} (${Short.SIZE_BITS} bit)")
println("Int : ${Int.MIN_VALUE} .. ${Int.MAX_VALUE} (${Int.SIZE_BITS} bit)")
println("Long : ${Long.MIN_VALUE} .. ${Long.MAX_VALUE} (${Long.SIZE_BITS} bit)")
println()
val kapasitasByte: Byte = 100
val kapasitasShort: Short = 30_000
val jumlahItem: Int = 2_000_000
val mikrodetik: Long = 1_500_000_000L
println("kapasitasByte = $kapasitasByte")
println("kapasitasShort = $kapasitasShort")
println("jumlahItem = $jumlahItem")
println("mikrodetik = $mikrodetik")
println()
println("Demonstrasi overflow (wrap-around):")
val maxInt = Int.MAX_VALUE
val tambahSatu = maxInt + 1
println("Int.MAX_VALUE = $maxInt")
println("maxInt + 1 = $tambahSatu <- terbungkus ke minimum")
val maxByte = Byte.MAX_VALUE
val toByteOverflow = (maxByte + 1).toByte()
println("Byte.MAX_VALUE = $maxByte")
println("(maxByte+1).toByte() = $toByteOverflow")
println()
println("Tipe unsigned:")
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 (range ${UByte.MIN_VALUE} .. ${UByte.MAX_VALUE})")
println("uShort = $uShort (range ${UShort.MIN_VALUE} .. ${UShort.MAX_VALUE})")
println("uInt = $uInt")
println("uLong = $uLong")
}Output yang Dihasilkan:
Range tipe integer:
Byte : -128 .. 127 (8 bit)
Short : -32768 .. 32767 (16 bit)
Int : -2147483648 .. 2147483647 (32 bit)
Long : -9223372036854775808 .. 9223372036854775807 (64 bit)
kapasitasByte = 100
kapasitasShort = 30000
jumlahItem = 2000000
mikrodetik = 1500000000
Demonstrasi overflow (wrap-around):
Int.MAX_VALUE = 2147483647
maxInt + 1 = -2147483648 <- terbungkus ke minimum
Byte.MAX_VALUE = 127
(maxByte+1).toByte() = -128
Tipe unsigned:
uByte = 200 (range 0 .. 255)
uShort = 60000 (range 0 .. 65535)
uInt = 4000000000
uLong = 18000000000000000000Mari kita amati baris-baris penting pada kode di atas:
- Baris 2-5 (
Byte.MIN_VALUEdst.) — setiap tipe integer memiliki propertiMIN_VALUEdanMAX_VALUE. Property ini berguna untuk validasi sebelum konversi tipe. - Baris 8-11 — deklarasi dengan tipe eksplisit.
Bytecocok untuk data biner (0-255 signed menjadi -128..127);Longwajib untuk angka di luarInt.MAX_VALUE. - Baris 17-18 (
maxInt + 1) — penambahanInt.MAX_VALUE + 1menghasilkanInt.MIN_VALUEkarena wrap-around. Tidak ada exception yang dilempar; kompilator membiarkan operasi berjalan dan hasilnya melingkar. - Baris 21-22 (
(maxByte + 1).toByte()) —maxByte + 1menghasilkanInt(128)..toByte()memotong keByte, yang melingkari ke-128. Ini menunjukkan bahwa operasi aritmatika padaByte/Shortdi-promosikan keIntdahulu. - Baris 27-30 (
200u, dst.) — suffixumenandakan literal unsigned.UByte200 sah karena muat di rentang unsigned0 .. 255, padahal padaBytesigned nilai 200 tidak valid.
Perilaku overflow #
Kotlin tidak memeriksa overflow integer saat runtime. Operasi yang melampaui batas akan wrap-around:
val max = Int.MAX_VALUE // 2147483647
val overflow = max + 1 // -2147483648 (wrap-around)
val min = Int.MIN_VALUE // -2147483648
val underflow = min - 1 // 2147483647 (wrap-around)Untuk mendeteksi overflow secara eksplisit, Kotlin menyediakan method addExact, multiplyExact, subtractExact pada java.lang.Math:
import java.lang.Math.multiplyExact
val aman = multiplyExact(1_000_000, 1_000_000) // 1_000_000_000
// val bahaya = multiplyExact(Int.MAX_VALUE, 2) // ArithmeticExceptionPromosi tipe pada operasi #
Berikut tabel promosi otomatis pada operasi aritmatika:
| Operan kiri | Operan kanan | Hasil |
|---|---|---|
Byte | Byte | Int |
Short | Short | Int |
Int | Int | Int |
Long | Long | Long |
Int | Long | Long |
Promosi ini adalah warisan JVM untuk efisiensi CPU. Kita tetap dapat menulis kode yang menggunakan Byte/Short, tetapi harus sadar bahwa hasil operasi akan menjadi Int.
Perkenalan tipe unsigned #
Tipe unsigned berguna ketika kita tahu nilai tidak pernah negatif:
| Tipe | Lebar | Rentang | Contoh penggunaan |
|---|---|---|---|
UByte | 8 bit | 0 .. 255 | Komponen RGB, byte stream |
UShort | 16 bit | 0 .. 65.535 | Port jaringan, code point UTF-16 |
UInt | 32 bit | 0 .. 4.294.967.295 | ID database di atas 2^31 |
ULong | 64 bit | 0 .. 2^64-1 | Ukuran file besar, hash |
Penggunaan tipe unsigned dibahas tuntas pada chapter Unsigned Integer Types, termasuk kapan memakainya dan kapan menghindarinya.
Referensi Lanjutan #
- Numbers
— dokumentasi tipe angka Kotlin yang merinci ukuran dan rentang
Byte,Short,Int, sertaLong
Pemilihan tipe integer bergantung pada rentang nilai dan kebutuhan memori. Berikutnya, kita akan melihat tipe floating-point dan jebakan presisi yang menyertainya — materi pada chapter Floating-Point Types.