Kita sudah bisa mendeklarasikan variabel, tetapi Java menyediakan lebih dari satu cara melakukannya — ada deklarasi yang langsung diisi, ada yang ditunda, bahkan ada yang mengumpanyulkan beberapa nama dalam satu statement. Di balik variasi tersebut, compiler javac menjalankan analisis ketat bernama definite assignment: setiap variabel lokal harus terbukti sudah berisi nilai sebelum dipakai. Pada Chapter ini kita susun seluruh pola deklarasi dan inisialisasi, lalu menguji apa yang terjadi bila aturan tersebut dilanggar.

Empat Pola Deklarasi #

Dalam praktik sehari-hari, deklarasi variabel lokal muncul dalam empat pola:

  • Deklarasi lalu assignment terpisah: int stok; diikuti stok = 40; — cocok saat nilai awal baru diketahui beberapa baris kemudian, misalnya setelah membaca masukan pengguna.
  • Deklarasi dengan inisialisasi langsung: int terjual = 12; — pola tersering dan paling disarankan karena nilai variabel tidak pernah menggantung kosong.
  • Inisialisasi dari ekspresi: int sisa = stok - terjual; — sisi kanan = boleh berupa ekspresi apa pun yang tipenya sesuai, termasuk pemanggilan method.
  • Banyak nama dalam satu statement: int porsiA = 5, porsiB = 8; — satu tipe untuk beberapa nama, dipisah koma. Praktis untuk variabel berkerabat, tetapi jangan berlebihan hingga satu baris memuat puluhan nama.

Empat Pola dalam Satu Program #

Program berikut mempraktikkan keempat pola tersebut dalam alur tokot sederhana:

public class BentukDeklarasi {
    public static void main(String[] args) {
        int stok;                     // 1) deklarasi dulu, tanpa nilai
        stok = 40;                    //    lalu assignment terpisah

        int terjual = 12;             // 2) deklarasi + inisialisasi sekaligus

        int sisa = stok - terjual;    // 3) inisialisasi dari ekspresi

        int porsiA = 5, porsiB = 8, total = porsiA + porsiB; // 4) banyak nama

        String label = "Sisa stok hari ini: " + sisa;

        System.out.println("stok    = " + stok);
        System.out.println("terjual = " + terjual);
        System.out.println("sisa    = " + sisa);
        System.out.println("total   = " + total);
        System.out.println(label);
    }
}

Output yang Dihasilkan:

text
stok    = 40
terjual = 12
sisa    = 28
total   = 13
Sisa stok hari ini: 28

Mari kita bedah baris-baris kuncinya:

  1. Baris 3-4 (int stok; lalu stok = 40;): antara deklarasi dan assignment, variabel stok dikenal compiler tetapi tidak boleh dipakai. Setelah baris ke-4, stok resmi berisi 40.
  2. Baris 8 (int sisa = stok - terjual;): sisi kanan dievaluasi memakai nilai dua variabel sebelumnya (40 - 12 = 28), lalu hasilnya menjadi nilai awal sisa. Urutan baris penting — stok dan terjual harus sudah berisi nilai pada saat baris ini dieksekusi.
  3. Baris 10 (int porsiA = 5, porsiB = 8, total = porsiA + porsiB;): tiga nama bertipe int dalam satu statement. Perhatikan bahwa total boleh memakai porsiA dan porsiB karena kedua nama tersebut sudah diinisialisasi pada klausa sebelumnya dalam statement yang sama.
  4. Baris 12 (String label = ...): inisialisasi juga boleh menggabungkan teks — operator + antara String dan angka menghasilkan String baru.

Definite Assignment #

Compiler Java tidak hanya memeriksa tipe — compiler juga menelusuri alur program untuk memastikan setiap variabel lokal sudah pasti berisi nilai saat dibaca. Analisis ini bernama definite assignment (JLS §16). Konsekuensinya menarik: variabel boleh dideklarasikan dulu dan diisi di dalam percabangan, asalkan semua jalur menuju titik pembacaan mengisi variabel tersebut.

Program berikut menunda inisialisasi kategori ke dalam blok if/else, lalu mengakumulasi nilai total di dalam loop:

public class InisialisasiBersyarat {
    public static void main(String[] args) {
        int umur = 17;
        String kategori;

        if (umur >= 17) {
            kategori = "dewasa";
        } else {
            kategori = "anak";
        }
        System.out.println("kategori = " + kategori);

        int total = 0;
        for (int i = 1; i <= 5; i++) {
            total += i;               // inisialisasi berangsur di dalam loop
        }
        System.out.println("total    = " + total);
    }
}

Output yang Dihasilkan:

text
kategori = dewasa
total    = 15

Dua mekanisme menonjol di sini:

  1. Baris 4 dan 6-10 (kategori): kategori dideklarasikan kosong, lalu diisi di kedua cabang if/else. Compiler menerima pola ini karena jalur manapun yang diambil — kondisi benar atau salah — variabel kategori pasti terisi sebelum baris 11 membacanya.
  2. Baris 14-17 (total dan total += i): variabel akumulator diinisialisasi 0 lebih dulu, lalu nilainya bertambah setiap putaran loop. Tanpa inisialisasi total = 0 di awal, statement total += i akan ditolak compiler karena membaca nilai yang belum ada.

Variabel Lokal yang Dipakai Tanpa Inisialisasi #

Bentuk pelanggaran paling sederhana: variabel dideklarasikan lalu langsung dibaca. Berkas berikut sengaja memuat kesalahan tersebut:

public class LupaInisialisasi {
    public static void main(String[] args) {
        int skor;
        System.out.println(skor);
    }
}

Compiler javac menolak berkas tersebut dengan pesan error: variable skor might not have been initialized yang menunjuk ke pemakaian skor pada baris println. Perhatikan asimetri yang sudah kita bahas pada Chapter Reference Types: variabel lokal wajib diinisialisasi secara eksplisit, sedangkan field di dalam objek mendapat nilai bawaan otomatis (0, false, null). Asimetri ini disengaja — field hidup di objek yang diurus JVM, sementara variabel lokal di stack frame tidak dibersihkan dan tidak diinisialisasi JVM, sehingga compiler memaksa kita menulis nilai awal secara eksplisit.

Empat pola deklarasi di atas menuntut kita mengetik tipe secara eksplisit — int, String, double — bahkan ketika tipenya sudah jelas terbaca dari nilai inisialisasinya. Sejak Java 10, compiler dapat menyimpulkan tipe tersebut untuk kita lewat kata kunci var. Chapter berikutnya, Type Inference dengan var, membahas kapan fasilitas ini mempermudah dan kapan fasilitas ini justru dilarang dipakai.

Referensi #

Berkas Sumber

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

BentukDeklarasi.java

Unduh berkas
java
public class BentukDeklarasi {
    public static void main(String[] args) {
        int stok;                     // 1) deklarasi dulu, tanpa nilai
        stok = 40;                    //    lalu assignment terpisah

        int terjual = 12;             // 2) deklarasi + inisialisasi sekaligus

        int sisa = stok - terjual;    // 3) inisialisasi dari ekspresi

        int porsiA = 5, porsiB = 8, total = porsiA + porsiB; // 4) banyak nama

        String label = "Sisa stok hari ini: " + sisa;

        System.out.println("stok    = " + stok);
        System.out.println("terjual = " + terjual);
        System.out.println("sisa    = " + sisa);
        System.out.println("total   = " + total);
        System.out.println(label);
    }
}

InisialisasiBersyarat.java

Unduh berkas
java
public class InisialisasiBersyarat {
    public static void main(String[] args) {
        int umur = 17;
        String kategori;

        if (umur >= 17) {
            kategori = "dewasa";
        } else {
            kategori = "anak";
        }
        System.out.println("kategori = " + kategori);

        int total = 0;
        for (int i = 1; i <= 5; i++) {
            total += i;               // inisialisasi berangsur di dalam loop
        }
        System.out.println("total    = " + total);
    }
}

LupaInisialisasi.java

Unduh berkas
java
public class LupaInisialisasi {
    public static void main(String[] args) {
        int skor;
        System.out.println(skor);
    }
}