Menulis program Java lengkap hanya untuk menjawab satu pertanyaan kecil — “method apa yang tersedia di String?” atau “bagaimana format DateTimeFormatter untuk pola tertentu?” — terasa berat. Sejak JDK 9, JDK menyertakan jshell: lingkungan REPL (Read-Eval-Print Loop) yang mengevaluasi potongan kode Java satu per satu dan langsung menampilkan hasilnya. Kekuatannya bukan sekadar kecepatan, melainkan state yang persisten: variabel, method, dan class yang kita definisikan pada satu potongan tetap hidup untuk potongan berikutnya dalam sesi yang sama. Section Scripting dan Automation dibuka dengan alat ini karena jshell adalah pintu masuk paling cepat ke semua topik sesudahnya. Semua keluaran pada chapter ini dikutip dari sesi jshell sungguhan pada JDK 25.
Sesi Interaktif dan State yang Persisten #
Jalankan jshell dari terminal, lalu ketik potongan kode — akhiri dengan Enter, bukan titik koma wajib. Sesi berikut mendefinisikan dua variabel lalu menjumlahkannya:
$ jshell
| Welcome to JShell -- Version 25.0.4.1
| For an introduction type: /help intro
jshell> int a = 10;
a ==> 10
jshell> int b = 32;
b ==> 32
jshell> a + b
$3 ==> 42Dua hal penting terlihat di keluaran itu. Pertama, tanda ==> menampilkan nilai hasil evaluasi — deklarasi menampilkan nilai variabelnya, sedangkan ekspresi lepas mendapat nama otomatis $1, $2, $3, dan seterusnya sehingga bisa dipakai ulang: $3 * 2 menghasilkan 84. Kedua, baris ketiga tidak mendeklarasikan apa pun — jshell tetap mengevaluasinya karena state sesi (variabel a dan b) masih hidup. Deklarasi class dan record bekerja sama mulusnya — record Pegawai(String nama, int gaji) { } diikuti balasan | created record Pegawai dan langsung bisa dipakai pada baris berikutnya.
Perintah Pengelolaan Sesi #
Seluruh perintah internal diawali garis miring dan tidak memerlukan titik koma. Yang terpenting untuk alur kerja harian:
| Perintah | Fungsi |
|---|---|
/list | tampilkan semua potongan yang sudah dieksekusi |
/vars, /methods | daftar variabel dan method aktif beserta tipenya |
/edit nama | ubah potongan di editor jendela |
/drop nama | hapus potongan dari sesi |
/reset | kosongkan seluruh state sesi |
/save berkas.jsh | simpan potongan sesi ke berkas |
/open berkas.jsh | muat potongan dari berkas ke sesi |
/exit | tutup jshell |
Pasangan /save dan /open adalah jembatan antara eksperimen dan berkas. Sesi berikut menyimpan satu deklarasi lalu memuatnya kembali pada sesi baru:
jshell> int a = 5;
a ==> 5
jshell> /save sesi-simpan.jsh
jshell> /exit
| Goodbye
$ jshell
jshell> /open sesi-simpan.jsh
jshell> a
a ==> 5Skrip .jsh dan Mode Feedback #
Berkas berisi rangkaian potongan — biasanya berekstensi .jsh — bisa dijalankan tanpa interaksi sama sekali, pola yang pas untuk demonstrasi dan pengujian cepat. Skrip berikut memakai record, stream, dan method reference dalam satu berkas:
$ cat sesi.jsh
var daftar = new java.util.ArrayList<String>();
daftar.add("Budi");
daftar.add("Siti");
daftar.add("Dewi");
daftar.stream().filter(n -> n.length() == 4).forEach(System.out::println)
/exitMenjalankannya dengan mode senyap -q hanya menampilkan keluaran program — balasan ==> dari jshell disembunyikan:
$ jshell -q sesi.jsh
Budi
Siti
DewiPilihan mode feedback menentukan seberapa banyak jshell berbicara. Mode silent (-s) menyembunyikan hampir semuanya, mode quiet (-q) menampilkan hasil evaluasi tanpa banner, mode normal menampilkan semuanya, dan mode verbose (-v) menambahkan tipe hasil tiap ekspresi — berguna saat belajar karena menampilkan int, String, atau tipe generik di belakang var.
JShell API — Evaluator dalam Program #
Kemampuan evaluasi jshell juga tersedia sebagai library lewat package jdk.jshell. Satu instance JShell adalah satu sesi utuh: potongan dievaluasi berurutan dan state menempel pada instance itu. Program berikut menjalankan empat potongan melalui API — termasuk satu yang melempar exception:
import jdk.jshell.JShell;
import jdk.jshell.SnippetEvent;
import java.util.List;
public class EvaluasiPotongan {
public static void main(String[] args) {
// JShell API: evaluator yang sama dengan tool jshell.
try (JShell shell = JShell.create()) {
String[] potongan = {
"int luas = 6 * 7;",
"luas + 6",
"\"Halo \" + \"REPL\"",
"luas / 0"
};
for (String p : potongan) {
List<SnippetEvent> peristiwa = shell.eval(p);
SnippetEvent e = peristiwa.get(0);
if (e.exception() != null) {
System.out.printf("%-22s -> galat=%s: %s%n", p,
e.exception().getClass().getSimpleName(),
e.exception().getMessage());
} else {
System.out.printf("%-22s -> nilai=%s%n", p, e.value());
}
}
}
}
}Output yang Dihasilkan:
int luas = 6 * 7; -> nilai=42
luas + 6 -> nilai=48
"Halo " + "REPL" -> nilai="Halo REPL"
luas / 0 -> galat=EvalException: / by zeroMari kita telaah baris-baris kuncinya:
- Baris
try (JShell shell = JShell.create()):JShellmengimplementasikanAutoCloseable— try-with-resources memastikan sumber daya evaluator dilepas; tanpa penutupan, proses bisa tetap memegang thread internal. - Baris
shell.eval(p): mengembalikan daftarSnippetEvent— satu potongan bisa memicu beberapa peristiwa (misalnya deklarasi banyak variabel); kita mengambil yang pertama. - Baris
e.value(): hasil evaluasi sebagai string, persis bentuk yang ditampilkan setelah tanda==>di sesi interaktif —"Halo REPL"lengkap dengan tanda kutipnya. - Baris
e.exception(): exception runtime dari potongan dibungkusEvalExceptiondengan pesan aslinya (/ by zero) — evaluator tidak mati; potongan berikutnya tetap dievaluasi. - Urutan potongan kedua:
luas + 6hanya bermakna karena potongan pertama masih menempel pada sesi yang sama — state persisten dari REPL berlaku identik pada API.
REPL menjawab pertanyaan satu potongan; aplikasi sungguhan menerima banyak masukan sekaligus lewat command line. Chapter berikutnya membahas rancangan program CLI yang rapi — exit code, pesan bantuan, dan konvensi keluaran.
Referensi #
- Oracle: Introduction to JShell
- Oracle: JShell API (jdk.jshell.JShell)
- Oracle: jshell Command Reference
Berkas Sumber
Berkas pendukung halaman ini dapat diunduh dan dijalankan langsung sesuai penjelasan di atas.
EvaluasiPotongan.java
Unduh berkasimport jdk.jshell.JShell;
import jdk.jshell.SnippetEvent;
import java.util.List;
public class EvaluasiPotongan {
public static void main(String[] args) {
// JShell API: evaluator yang sama dengan tool jshell.
try (JShell shell = JShell.create()) {
String[] potongan = {
"int luas = 6 * 7;",
"luas + 6",
"\"Halo \" + \"REPL\"",
"luas / 0"
};
for (String p : potongan) {
List<SnippetEvent> peristiwa = shell.eval(p);
SnippetEvent e = peristiwa.get(0);
if (e.exception() != null) {
System.out.printf("%-22s -> galat=%s: %s%n", p,
e.exception().getClass().getSimpleName(),
e.exception().getMessage());
} else {
System.out.printf("%-22s -> nilai=%s%n", p, e.value());
}
}
}
}
}