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:

text
$ 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 ==> 42

Dua 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:

PerintahFungsi
/listtampilkan semua potongan yang sudah dieksekusi
/vars, /methodsdaftar variabel dan method aktif beserta tipenya
/edit namaubah potongan di editor jendela
/drop namahapus potongan dari sesi
/resetkosongkan seluruh state sesi
/save berkas.jshsimpan potongan sesi ke berkas
/open berkas.jshmuat potongan dari berkas ke sesi
/exittutup jshell

Pasangan /save dan /open adalah jembatan antara eksperimen dan berkas. Sesi berikut menyimpan satu deklarasi lalu memuatnya kembali pada sesi baru:

text
jshell> int a = 5;
a ==> 5

jshell> /save sesi-simpan.jsh

jshell> /exit
|  Goodbye

$ jshell
jshell> /open sesi-simpan.jsh

jshell> a
a ==> 5

Skrip .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:

text
$ 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)
/exit

Menjalankannya dengan mode senyap -q hanya menampilkan keluaran program — balasan ==> dari jshell disembunyikan:

text
$ jshell -q sesi.jsh
Budi
Siti
Dewi

Pilihan 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:

text
int luas = 6 * 7;      -> nilai=42
luas + 6               -> nilai=48
"Halo " + "REPL"       -> nilai="Halo REPL"
luas / 0               -> galat=EvalException: / by zero

Mari kita telaah baris-baris kuncinya:

  1. Baris try (JShell shell = JShell.create()): JShell mengimplementasikan AutoCloseable — try-with-resources memastikan sumber daya evaluator dilepas; tanpa penutupan, proses bisa tetap memegang thread internal.
  2. Baris shell.eval(p): mengembalikan daftar SnippetEvent — satu potongan bisa memicu beberapa peristiwa (misalnya deklarasi banyak variabel); kita mengambil yang pertama.
  3. Baris e.value(): hasil evaluasi sebagai string, persis bentuk yang ditampilkan setelah tanda ==> di sesi interaktif — "Halo REPL" lengkap dengan tanda kutipnya.
  4. Baris e.exception(): exception runtime dari potongan dibungkus EvalException dengan pesan aslinya (/ by zero) — evaluator tidak mati; potongan berikutnya tetap dievaluasi.
  5. Urutan potongan kedua: luas + 6 hanya 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 #

Berkas Sumber

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

EvaluasiPotongan.java

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