Berapa hasil byte + byte? Kalau kita menjawab byte, kita baru saja terpeleset ke jebakan klasik Java: hasilnya adalah int. Sebelum operator aritmetika menyentuh operand, Java diam-diam mengubah tipe operand mengikuti aturan numeric promotion yang dirumuskan di JLS §5.6. Promosi inilah alasan byte jumlah = a + b; ditolak compiler, alasan 'A' + 1 menghasilkan int, dan alasan 7 / 2 menghasilkan 3 sedangkan 7.0 / 2 menghasilkan 3.5. Pada Chapter ini kita bedah aturannya, membuktikan tiap kasus dengan program, lalu membongkar pengecualian mengejutkan pada operator penugasan gabungan.
Aturan Promosi Biner #
Untuk operator biner seperti +, -, *, /, dan %, Java menerapkan binary numeric promotion dengan urutan keputusan sebagai berikut:
- Jika salah satu operand bertipe
double, operand lain dipromosikan kedouble. - Jika tidak, jika salah satu operand bertipe
float, keduanya menjadifloat. - Jika tidak, jika salah satu operand bertipe
long, keduanya menjadilong. - Jika tidak, kedua operand dipromosikan ke
int—byte,short, dancharselalu naik keint.
Singkatnya: tipe terbesar menang, dan int adalah lantai minimalnya. Operand byte, short, atau char tidak pernah bertahan sebagai tipe aslinya di dalam operasi biner; CPU umumnya juga tidak memiliki instruksi khusus untuk aritmetika 8 atau 16 bit, sehingga Java menyederhanakan bahasanya dengan satu lantai int.
Untuk operator unary seperti negasi -x atau ++, aturan serupa berlaku: byte, short, dan char dipromosikan ke int sebelum operasi dihitung.
Promosi dalam Berbagai Kombinasi #
Program berikut menguji lima kombinasi tipe yang paling sering dijumpai:
public class PromosiBiner {
public static void main(String[] args) {
byte a = 10, b = 20;
int hasilByte = a + b; // byte + byte -> int
System.out.println("byte + byte = int : " + hasilByte);
short s = 300;
int hasilShort = s + s; // short + short -> int
System.out.println("short + short = int : " + hasilShort);
char huruf = 'A';
int kodeBerikut = huruf + 1; // char + int -> int
System.out.println("'A' + 1 = int : " + kodeBerikut);
long populasi = 8_600_000L;
long tambah = populasi + 1000; // long + int -> long
System.out.println("long + int = long : " + tambah);
double rasio = 7.0 / 2; // double / int -> double
System.out.println("7.0 / 2 = " + rasio);
System.out.println("7 / 2 = " + (7 / 2)); // int / int -> int
}
}Output yang Dihasilkan:
byte + byte = int : 30
short + short = int : 600
'A' + 1 = int : 66
long + int = long : 8601000
7.0 / 2 = 3.5
7 / 2 = 3Mari kita bedah hasil-hasilnya:
- Baris 4-5 (
byte + byte): meski kedua operand bertipebyte, hasilnya bertipeintbernilai30. Variabel penampung pun harus bertipeint(atau lebih besar). - Baris 8-9 (
short + short): aturan yang sama —600tersimpan sebagaiint. - Baris 11-12 (
'A' + 1):chardipromosikan keintsehingga nilainya menjadi kode Unicode65, lalu dijumlah1menjadi66. Untuk mengembalikannya menjadichar, kita perlu cast eksplisit:char next = (char) (huruf + 1);. - Baris 14-15 (
long + int): tipe terbesar menang —1000yang semulaintnaik kelas menjadilong, hasil8601000bertipelong. - Baris 17-19 (
7.0 / 2vs7 / 2): satu operanddoublemenarik seluruh operasi ke ranah floating-point (3.5). Tanpa operand desimal, pembagianintolehintmemotong pecahan dan menghasilkan3— bukan pembulatan, melainkan pemotongan seperti pada Chapter Type Casting.
Menyimpan Hasil Kembali ke byte #
Konsekuensi paling nyata dari promosi muncul saat kita mencoba menampung hasil operasi kembali ke tipe kecil. Berkas berikut menolak dikompilasi:
public class PromosiDitolak {
public static void main(String[] args) {
byte a = 10, b = 20;
byte jumlah = a + b;
System.out.println(jumlah);
}
}Compiler javac menolak baris byte jumlah = a + b; dengan pesan error: incompatible types: possible lossy conversion from int to byte. Ekspresi a + b bertipe int (akibat promosi), sedangkan variabel tujuan bertipe byte — dan konversi int → byte adalah narrowing yang menuntut cast eksplisit. Perbaikannya: tulis byte jumlah = (byte) (a + b);, atau lebih sehat, gunakan variabel bertipe int sebagai penampung.
Pengecualian: Compound Assignment #
Operator penugasan gabungan seperti +=, -=, *=, dan /= menyimpan satu rahasia: operator tersebut melakukan cast implisit ke tipe variabel kiri. stok += 1 secara efektif diterjemahkan menjadi stok = (byte) (stok + 1) — promosi tetap terjadi, tetapi hasilnya dipangkas otomatis tanpa protes compiler.
Program berikut memperlihatkan konsekuensinya:
public class PenugasanGabungan {
public static void main(String[] args) {
byte stok = 127; // nilai maksimum byte
stok += 1; // compound assignment: cast implisit
System.out.println("stok setelah += 1 : " + stok);
stok = 100;
stok += 50; // 100 + 50 = 150, dipangkas ke byte
System.out.println("stok setelah += 50: " + stok);
int tinggi = 170;
tinggi /= 3; // 170 / 3 dipotong ke 56
System.out.println("tinggi /= 3 : " + tinggi);
}
}Output yang Dihasilkan:
stok setelah += 1 : -128
stok setelah += 50: -106
tinggi /= 3 : 56Tiga baris kunci pada program di atas:
- Baris 4 (
stok += 1;):127 + 1dihitung sebagaiintbernilai128, lalu dipangkas kebyte— hasilnya-128, tepat di ujung minimum rentang. Tidak ada error, tidak ada peringatan; nilai melipat menjadi negatif. - Baris 7-8 (
stok += 50;):150sebagaiintdipangkas ke delapan bit bertanda sehingga menjadi-106— mekanisme yang sama dengan cast(byte) 150pada Chapter sebelumnya. - Baris 10-11 (
tinggi /= 3;): pembagian170 / 3menghasilkan56karena pecahan dipotong;tinggibertipeintsehingga tidak ada pangkasan bit, hanya pemotongan pecahan khas pembagian integer.
Aturan promosi menjelaskan anatomi terakhir dari operasi antar tipe. Kini kita siap menghadapi topik yang paling sering menjatuhkan program nyata: apa yang terjadi ketika hasil hitungan melampaui rentang tipenya sendiri — bukan karena dipangkas cast, melainkan karena aritmetika murni yang berjalan melewati batas. Chapter Integer Overflow membedah fenomena melipatnya angka tersebut dan alat bawaan JDK untuk mendeteksinya.
Referensi #
- JLS SE25 §5.6: Numeric Promotions
- JLS SE25 §15.26.2: Compound Assignment Operators
- Oracle: Numbers in Java
Berkas Sumber
Berkas pendukung halaman ini dapat diunduh dan dijalankan langsung sesuai penjelasan di atas.
PenugasanGabungan.java
Unduh berkaspublic class PenugasanGabungan {
public static void main(String[] args) {
byte stok = 127; // nilai maksimum byte
stok += 1; // compound assignment: cast implisit
System.out.println("stok setelah += 1 : " + stok);
stok = 100;
stok += 50; // 100 + 50 = 150, dipangkas ke byte
System.out.println("stok setelah += 50: " + stok);
int tinggi = 170;
tinggi /= 3; // 170 / 3 dipotong ke 56
System.out.println("tinggi /= 3 : " + tinggi);
}
}
PromosiBiner.java
Unduh berkaspublic class PromosiBiner {
public static void main(String[] args) {
byte a = 10, b = 20;
int hasilByte = a + b; // byte + byte -> int
System.out.println("byte + byte = int : " + hasilByte);
short s = 300;
int hasilShort = s + s; // short + short -> int
System.out.println("short + short = int : " + hasilShort);
char huruf = 'A';
int kodeBerikut = huruf + 1; // char + int -> int
System.out.println("'A' + 1 = int : " + kodeBerikut);
long populasi = 8_600_000L;
long tambah = populasi + 1000; // long + int -> long
System.out.println("long + int = long : " + tambah);
double rasio = 7.0 / 2; // double / int -> double
System.out.println("7.0 / 2 = " + rasio);
System.out.println("7 / 2 = " + (7 / 2)); // int / int -> int
}
}
PromosiDitolak.java
Unduh berkaspublic class PromosiDitolak {
public static void main(String[] args) {
byte a = 10, b = 20;
byte jumlah = a + b;
System.out.println(jumlah);
}
}