Menulis JSON, SQL, atau templat HTML sebagai String literal biasa adalah pekerjaan berulang yang melelahkan: setiap baris ditutup kutip, ditempel \n, dibuka kutip lagi, dan tanda kutip di dalam teks harus di-escape menjadi \". Java 15 merampungkan persoalan tersebut dengan text block — literal yang dibuka dan ditutup tiga tanda kutip ganda (""") dan boleh memuat baris sebanyak apa pun dengan format yang hampir apa adanya. Chapter ini membahas aturan pembukaannya, perilaku incidental indentation yang menentukan indentasi hasil, escape khusus \s, serta cara menampilkan tiga tanda kutip di dalam text block.
Sebelum Ada Text Block #
Untuk menghargai nilai text block, mari kita lihat dulu cara lamanya. JSON tiga baris yang sama, bila ditulis sebagai literal biasa, harus dirakit dari potongan-potongan yang digabungkan operator +, lengkap dengan \n di setiap sambungan dan escape \" pada setiap tanda kutip:
String jsonLama = "{\n" +
" \"nama\": \"Budi\",\n" +
" \"kota\": \"Bandung\"\n" +
"}";Bentuk seperti ini sah dan masih sering dijumpai pada kode lawas. Persoalannya bukan pada kebenaran, melainkan pada keterbacaan: bentuk hasil tidak lagi mirip dengan teks sesungguhnya karena indentasi harus ditulis manual di dalam potongan literal, tanda kutip menumpuk dengan escape, dan satu baris logika dipecah menjadi empat baris sumber. Menambah satu field baru pada JSON di atas menuntut menyunting dua sambungan sekaligus — pekerjaan yang rawan salah ketik.
Text block hadir melalui proses JEP yang panjang: pratinjau pertama pada Java 13 (JEP 355), disempurnakan pada Java 14 (JEP 368) dengan penambahan escape \s dan \ penyambung baris, lalu difinalkan pada Java 15 melalui JEP 378. Sejak versi tersebut, text block adalah fitur bahasa permanen yang bisa dipakai tanpa penanda pratinjau apa pun.
Bentuk Dasar dan Aturan Pembuka #
Text block dimulai dengan """ diikuti wajib pindah baris — karakter pertama setelah pembuka tidak boleh berada di baris yang sama. Kedalaman indentasi hasil ditentukan oleh posisi penutup """: JVM mengukur indentasi minimum dari seluruh baris isi termasuk baris penutup, lalu membuang indentasi tersebut dari tiap baris. Karena itu, teks di dalam kode sumber bisa menjorok sejajar logika program, namun hasil String-nya tetap mulai dari kolom nol.
Dua aturan kecil melengkapi perilaku tersebut. Baris kosong di tengah isi dipertahankan apa adanya dan diikutsertakan dalam hasil, namun tidak ikut menentukan indentasi minimum — baris kosong tidak punya indentasi yang diukur. Dan karena penutup yang berdiri di baris sendiri ikut dihitung sebagai baris terakhir, hasil text block selalu diakhiri satu karakter baris baru; programmer yang butuh String tanpa baris baru terakhir cukup menaruh penutup di ujung baris isi terakhir.
public class BlokTeks {
public static void main(String[] args) {
String json = """
{
"nama": "Budi",
"kota": "Bandung",
"nilai": 85
}
""";
System.out.println("JSON:");
System.out.println(json);
String sql = """
SELECT nama, kota
FROM siswa
WHERE nilai > 80
""";
System.out.println("SQL:");
System.out.println(sql);
}
}Output yang Dihasilkan:
JSON:
{
"nama": "Budi",
"kota": "Bandung",
"nilai": 85
}
SQL:
SELECT nama, kota
FROM siswa
WHERE nilai > 80Mari kita telaah baris-baris kode di atas:
- Baris 3 (
String json = """): pembuka text block. Baris pembuka harus berakhir di situ — isi dimulai baris berikutnya, dan baris kosong pertama setelah pembuka tidak menjadi bagian hasil. - Baris 4-8 (isi JSON): tanda kutip ganda di dalam teks ditulis apa adanya tanpa escape — inilah keuntungan terbesar text block untuk JSON dan HTML. Inden kedalaman 16 spasi pada sumber dibuang otomatis karena baris penutup juga berada di kolom 16.
- **Baris 9 (
""";)**: penutup sejajar dengan baris isi paling dangkal. Karena penutup berada di baris tersendiri, hasil String diakhiri karakter baris baru setelah}` — terlihat dari baris kosong pemisah pada output. - Baris 13-19 (SQL): pola yang sama untuk kueri berbaris-baris. Kata-kata kunci SQL berdiri di kolom rapi tanpa satu pun
\natau+yang biasa menemani bentuk lama.
Escape dan Indentasi Relatif #
Dua hal berikut kerap membingungkan. Pertama, escape tetap bekerja di dalam text block — termasuk \s yang khusus hadir bersama fitur ini: escape tersebut merepresentasikan satu spasi yang dilindungi dari proses pembuangan indentasi, berguna menjaga spasi di ujung baris. Kedua, memindahkan baris penutup ke kolom yang berbeda menggeser seluruh indentasi hasil — indentasi relatif baris isi terhadap penutup adalah yang dipertahankan. Untuk menampilkan """ di dalam teks, cukup escape salah satu tanda kutipnya: \"\"\".
public class RacikBlokTeks {
public static void main(String[] args) {
String penjelasan = """
Text block dibuka dengan \"\"\" dan ditutup \"\"\".
Escape \\s mempertahankan spasi di akhir baris:\s
Baris ini tidak memakai escape.
""";
System.out.println(penjelasan);
System.out.println("---");
String rata = """
Apel
Jeruk
""";
String menjorok = """
Apel
Jeruk
""";
System.out.println("rata : [" + rata.replace("\n", "|") + "]");
System.out.println("menjorok: [" + menjorok.replace("\n", "|") + "]");
}
}Output yang Dihasilkan:
Text block dibuka dengan """ dan ditutup """.
Escape \s mempertahankan spasi di akhir baris:
Baris ini tidak memakai escape.
---
rata : [Apel|Jeruk|]
menjorok: [ Apel| Jeruk|]Bedah untuk contoh kedua:
- Baris 3-7 (text block pertama):
\"\"\"di-escape agar tiga tanda kutip tampil sebagai isi teks, bukan menutup blok. Baris isi kedua menampilkan\ssecara harfiah karena backslash-nya ditulis dengan escape ganda (\\s), sementara escape\stunggal di ujung baris yang sama mempertahankan satu spasi setelah tanda titik dua — spasi tersebut tidak ikut terbuang walau menempel di margin kanan baris sumber. - Baris 10-14 (
rata): penutup sejajar dengan isi, sehingga hasil bersih:Apel,Jeruk. Pemanggilan.replace("\n", "|")sekadar membuat baris baru terlihat di output sebagai karakter|. - Baris 15-19 (
menjorok): isi menjorok empat spasi lebih dalam daripada penutup, sehingga keempat spasi itu dipertahankan di hasil — terbukti outputApel| Jeruk|. Teknik ini berguna menyisipkan text block dengan indentasi tetap ke dalam teks lain, misalnya saat menyusun laporan bertingkat.
Text block menghasilkan String biasa — tidak ada tipe baru, sehingga seluruh method String, StringBuilder, hingga String.format bekerja seperti biasa di atasnya. Satu ranah yang mengambil manfaat terbesar adalah pola pencocokan teks berformat; kita tutup Section ini dengan topik yang lebih tajam: regular expressions.
Referensi #
Berkas Sumber
Berkas pendukung halaman ini dapat diunduh dan dijalankan langsung sesuai penjelasan di atas.
BlokTeks.java
Unduh berkaspublic class BlokTeks {
public static void main(String[] args) {
String json = """
{
"nama": "Budi",
"kota": "Bandung",
"nilai": 85
}
""";
System.out.println("JSON:");
System.out.println(json);
String sql = """
SELECT nama, kota
FROM siswa
WHERE nilai > 80
""";
System.out.println("SQL:");
System.out.println(sql);
}
}
RacikBlokTeks.java
Unduh berkaspublic class RacikBlokTeks {
public static void main(String[] args) {
String penjelasan = """
Text block dibuka dengan \"\"\" dan ditutup \"\"\".
Escape \\s mempertahankan spasi di akhir baris:\s
Baris ini tidak memakai escape.
""";
System.out.println(penjelasan);
System.out.println("---");
String rata = """
Apel
Jeruk
""";
String menjorok = """
Apel
Jeruk
""";
System.out.println("rata : [" + rata.replace("\n", "|") + "]");
System.out.println("menjorok: [" + menjorok.replace("\n", "|") + "]");
}
}