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:

  1. Jika salah satu operand bertipe double, operand lain dipromosikan ke double.
  2. Jika tidak, jika salah satu operand bertipe float, keduanya menjadi float.
  3. Jika tidak, jika salah satu operand bertipe long, keduanya menjadi long.
  4. Jika tidak, kedua operand dipromosikan ke int — byte, short, dan char selalu naik ke int.

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:

text
byte + byte  = int  : 30
short + short = int : 600
'A' + 1      = int  : 66
long + int   = long : 8601000
7.0 / 2      = 3.5
7 / 2        = 3

Mari kita bedah hasil-hasilnya:

  1. Baris 4-5 (byte + byte): meski kedua operand bertipe byte, hasilnya bertipe int bernilai 30. Variabel penampung pun harus bertipe int (atau lebih besar).
  2. Baris 8-9 (short + short): aturan yang sama — 600 tersimpan sebagai int.
  3. Baris 11-12 ('A' + 1): char dipromosikan ke int sehingga nilainya menjadi kode Unicode 65, lalu dijumlah 1 menjadi 66. Untuk mengembalikannya menjadi char, kita perlu cast eksplisit: char next = (char) (huruf + 1);.
  4. Baris 14-15 (long + int): tipe terbesar menang — 1000 yang semula int naik kelas menjadi long, hasil 8601000 bertipe long.
  5. Baris 17-19 (7.0 / 2 vs 7 / 2): satu operand double menarik seluruh operasi ke ranah floating-point (3.5). Tanpa operand desimal, pembagian int oleh int memotong pecahan dan menghasilkan 3 — 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:

text
stok setelah += 1 : -128
stok setelah += 50: -106
tinggi /= 3       : 56

Tiga baris kunci pada program di atas:

  1. Baris 4 (stok += 1;): 127 + 1 dihitung sebagai int bernilai 128, lalu dipangkas ke byte — hasilnya -128, tepat di ujung minimum rentang. Tidak ada error, tidak ada peringatan; nilai melipat menjadi negatif.
  2. Baris 7-8 (stok += 50;): 150 sebagai int dipangkas ke delapan bit bertanda sehingga menjadi -106 — mekanisme yang sama dengan cast (byte) 150 pada Chapter sebelumnya.
  3. Baris 10-11 (tinggi /= 3;): pembagian 170 / 3 menghasilkan 56 karena pecahan dipotong; tinggi bertipe int sehingga 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 #

Berkas Sumber

Berkas pendukung halaman ini dapat diunduh dan dijalankan langsung sesuai penjelasan di atas.

PenugasanGabungan.java

Unduh berkas
java
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);
    }
}

PromosiBiner.java

Unduh berkas
java
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
    }
}

PromosiDitolak.java

Unduh berkas
java
public class PromosiDitolak {
    public static void main(String[] args) {
        byte a = 10, b = 20;
        byte jumlah = a + b;
        System.out.println(jumlah);
    }
}