Tidak sedikit deklarasi di Java ditulis semata-mata karena tata bahasa menuntut adanya nama — padahal variabelnya tidak pernah dipakai. Loop yang hanya menghitung iterasi tetap menamai elemennya; catch yang hanya menandai kegagalan tetap mengikat variabel exception; try-with-resources tetap memberi nama sumber daya yang memang hanya perlu ditutup. Nama-nama semacam itu adalah kebisingan: pembaca mencari artinya, linter menandainya tidak terpakai. Unnamed variables, difinalkan di Java 22 melalui JEP 456, mengizinkan tanda _ menyatakan “variabel ini sengaja diabaikan” pada seluruh konteks itu — sekaligus menuntaskan sejarah panjang _ yang sejak Java 9 sudah tidak boleh dipakai sebagai nama. Chapter ini mempraktikkan seluruh konteksnya dengan satu program teruji.
Dari Nama Tak Terpakai Menjadi Penanda Niat #
Sebelum Java 22, _ berada dalam keadaan canggung: dilarang sebagai nama (int _ = 5; masih sah dideklarasikan di Java 8, lalu ditolak sejak Java 9), tetapi belum diberi peran baru. JEP 456 memberi peran itu: _ menjadi variabel tanpa nama yang boleh dideklarasikan berulang dalam scope berbeda dan tidak boleh dibaca — kompiler menolak rujukan apa pun dengan pesan underscore not allowed here, yang diverifikasi langsung pada JDK 25. Karena tidak bisa dibaca, variabel _ juga tidak menimbulkan peringatan “tidak terpakai”: diabaikan justru maknanya. Pada pattern, _ bekerja serupa sebagai pola yang cocok dengan apa pun tanpa mengikat apa pun.
Empat Konteks dalam Satu Program #
Contoh teruji berikut memakai _ sebagai lambda parameter, variabel lokal hasil deklarasi, variabel loop, komponen record pattern, dan parameter catch:
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
public class SisiKiri {
record Pasangan(int kunci, int nilai) { }
static final Map<String, List<Integer>> BUKU_NILAI = new LinkedHashMap<>();
static void catat(String siswa, Integer nilai) {
// Lambda: parameter siswa tidak dipakai di badan lambda.
BUKU_NILAI.computeIfAbsent(siswa, _ -> new ArrayList<>()).add(nilai);
}
static int catatSemua() {
catat("Budi", 80);
catat("Sita", 92);
catat("Budi", 75);
return 0; // nilai kembalian sengaja tidak dipedulikan
}
public static void main(String[] args) {
// 1) Deklarasi: efek samping dipakai, hasilnya diabaikan.
var _ = catatSemua();
// 2) Loop enhanced: hanya jumlah iterasi dibutuhkan.
int totalSiswa = 0;
for (var _ : BUKU_NILAI.keySet()) {
totalSiswa++;
}
// 3) Record pattern: komponen nilai sengaja tidak diikat.
Object p = new Pasangan(7, 99);
if (p instanceof Pasangan(int kunci, int _)) {
System.out.println("kunci : " + kunci);
}
// 4) catch tanpa variabel exception.
try {
Integer.parseInt("bukan angka");
} catch (NumberFormatException _) {
System.out.println("format angka : ditolak");
}
System.out.println("siswa tercatat : " + totalSiswa);
System.out.println("buku nilai : " + BUKU_NILAI);
}
}Output yang Dihasilkan:
kunci : 7
format angka : ditolak
siswa tercatat : 2
buku nilai : {Budi=[80, 75], Sita=[92]}Bedah baris-per-baris untuk bagian pentingnya:
- Baris
BUKU_NILAI.computeIfAbsent(siswa, _ -> new ArrayList<>()): lambda penerima kunci tidak memakai parameternya;_menggantikan nama sepertikatausiswaLagiyang hanya menipu pembaca. - Baris
var _ = catatSemua();: nilai kembalianintdaricatatSemua()sengaja dibuang — kita hanya ingin efek sampingnya mencatat nilai; tata bahasa tetap puas, pembaca tidak dibuat bertanya-tanya. - Baris
for (var _ : BUKU_NILAI.keySet()): loop hanya menghitung jumlah siswa; elemen tidak pernah dibaca, dan_menyatakannya di tempat. - Baris
if (p instanceof Pasangan(int kunci, int _)): record pattern mengikatkuncisaja; komponennilaidicocokkan strukturnya lalu diabaikan. - Blok
catch (NumberFormatException _): handler hanya mencetak pesan tetap; objek exception tidak dirujuk, dan stack trace pun tidak diperlukan.
Konteks Lengkap dan Sejarahnya #
| Konteks | Bentuk | Final sejak |
|---|---|---|
| Variabel lokal | var _ = hitung(); | Java 22 |
| Loop for / enhanced for | for (var _ : kumpulan) | Java 22 |
| try-with-resources | try (var _ = buka()) | Java 22 |
| catch | catch (IOException _) | Java 22 |
| Parameter lambda | peta.computeIfAbsent(k, _ -> ...) | Java 22 |
| Type pattern & record pattern | case Titik _ / case Titik(var x, _) | Java 22 |
Kebiasaan kecil ini menuntaskan peta fitur bahasa modern. Satu chapter tersisa di Section ini: bagaimana semua perubahan ini memasuki aplikasi lama tanpa menimbulkan keretakan — compatibility dan migration.
Referensi #
Berkas Sumber
Berkas pendukung halaman ini dapat diunduh dan dijalankan langsung sesuai penjelasan di atas.
SisiKiri.java
Unduh berkasimport java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
public class SisiKiri {
record Pasangan(int kunci, int nilai) { }
static final Map<String, List<Integer>> BUKU_NILAI = new LinkedHashMap<>();
static void catat(String siswa, Integer nilai) {
// Lambda: parameter siswa tidak dipakai di badan lambda.
BUKU_NILAI.computeIfAbsent(siswa, _ -> new ArrayList<>()).add(nilai);
}
static int catatSemua() {
catat("Budi", 80);
catat("Sita", 92);
catat("Budi", 75);
return 0; // nilai kembalian sengaja tidak dipedulikan
}
public static void main(String[] args) {
// 1) Deklarasi: efek samping dipakai, hasilnya diabaikan.
var _ = catatSemua();
// 2) Loop enhanced: hanya jumlah iterasi dibutuhkan.
int totalSiswa = 0;
for (var _ : BUKU_NILAI.keySet()) {
totalSiswa++;
}
// 3) Record pattern: komponen nilai sengaja tidak diikat.
Object p = new Pasangan(7, 99);
if (p instanceof Pasangan(int kunci, int _)) {
System.out.println("kunci : " + kunci);
}
// 4) catch tanpa variabel exception.
try {
Integer.parseInt("bukan angka");
} catch (NumberFormatException _) {
System.out.println("format angka : ditolak");
}
System.out.println("siswa tercatat : " + totalSiswa);
System.out.println("buku nilai : " + BUKU_NILAI);
}
}