Eğitim Portalı/Sürüm Analizi/Java 13 (Eylül 2019) — Detaylı Sürüm Analizi
Sürüm Analizi05-java-versiyon-analizi/06-Java-13

Java 13 (Eylül 2019) — Detaylı Sürüm Analizi

> Bu doküman, Java 13 ile gelen yenilikleri Türkçe, derinlemesine ve gerçek > hayat örnekleriyle anlatır. İlgili çalışan kod için bkz. TextBlocksPreview.java.

Java 13 (Eylül 2019) — Detaylı Sürüm Analizi

Bu doküman, Java 13 ile gelen yenilikleri Türkçe, derinlemesine ve gerçek hayat örnekleriyle anlatır. İlgili çalışan kod için bkz. TextBlocksPreview.java.


Sürüm Bilgisi

ÖzellikDeğer
Sürüm adıJava SE 13 / JDK 13
Çıkış tarihi17 Eylül 2019
Sürüm türüFeature Release (özellik sürümü, LTS DEĞİL)
Destek durumuKısa süreli (6 ay). LTS değildir; üretimde uzun süreli destek için Java 11 veya 17 tercih edilir.
Önceki sürümJava 12 (Mart 2019)
Sonraki sürümJava 14 (Mart 2020)

Java 13, 6 aylık sürüm temposunun bir parçasıdır. Yani devrim niteliğinde büyük bir değişiklik değil, kademeli (incremental) iyileştirmeler getirir. En çok konuşulan yeniliği Text Blocks'tur.

Java 13'teki JEP'ler (genel bakış)

JEPBaşlıkDurum (Java 13'te)
JEP 355Text BlocksPreview (Önizleme)
JEP 354Switch ExpressionsPreview (ikinci tur)yield eklendi
JEP 350Dynamic CDS ArchivesKalıcı
JEP 351ZGC: Uncommit Unused MemoryKalıcı (deneysel GC içinde iyileştirme)
JEP 353Reimplement the Legacy Socket APIKalıcı (iç altyapı)

Preview (Önizleme) Kavramı — Çok Önemli

Java, büyük dil özelliklerini doğrudan "kalıcı" yapmak yerine önce preview olarak yayınlar. Amaç: topluluktan geri bildirim toplamak ve özelliği olgunlaştırmak. Preview özellikleri:

  • Üretimde kullanılması tavsiye edilmez (sözdizimi değişebilir).
  • Derlemek için özel bayrak gerekir: javac --enable-preview --release 13 ...
  • Çalıştırmak için de bayrak gerekir: java --enable-preview ...

Bu sürümdeki iki özelliğin preview → kalıcı evrimi (NET)

TEXT BLOCKS
  Java 13  -> Preview (1. tur, JEP 355)
  Java 14  -> Preview (2. tur, JEP 368)  [+ \ ve \s kaçış dizileri eklendi]
  Java 15  -> KALICI / STANDARD (JEP 378)

SWITCH EXPRESSIONS
  Java 12  -> Preview (1. tur, JEP 325)  [ok-etiketli "case ->" söz dizimi]
  Java 13  -> Preview (2. tur, JEP 354)  [değer döndürmede "break value" KALDIRILDI,
                                          yerine "yield" anahtar kelimesi GELDİ]
  Java 14  -> KALICI / STANDARD (JEP 361)

Bu evrimi anlamak kritik: Java 13'ün en büyük katkısı yeni bir özellik icat etmek değil, Java 12'de başlayan iki özelliği olgunlaştırmaktır.


ÖZELLİK 1: Text Blocks (Önizleme — JEP 355)

İlgili dosya: TextBlocksPreview.java

NEDİR?

Text Blocks, çok satırlı string (string literal) yazmayı sağlayan yeni bir söz dizimidir. Üç çift tırnak (""") ile başlar ve biter:

String metin = """
        Birinci satır
        İkinci satır
        """;

NEDEN GELDİ? (Hangi problemi çözüyor?)

Java'da en eski ve en can sıkıcı sorunlardan biri, çok satırlı veya içinde tırnak geçen metinleri yazmaktı. Buna "kaçış karakteri cehennemi" (escape hell) denir:

  • Her satır ayrı bir "..." literal olmak zorundaydı.
  • Satırları + ile birleştirmek gerekiyordu.
  • Yeni satır için her satıra \n eklemek gerekiyordu.
  • Metnin içinde geçen her " işaretini \" olarak kaçırmak gerekiyordu.

Sonuç: Bir JSON, SQL veya HTML parçasını okumak/yazmak/bakımını yapmak işkenceye dönüşüyordu. Kod, asıl temsil ettiği metne hiç benzemiyordu.

NE İŞE YARAR?

  • Çok satırlı metni tam göründüğü gibi yazmayı sağlar.
  • \n, \", + birleştirme ihtiyacını ortadan kaldırır.
  • Girintiyi otomatik yönetir (incidental whitespace temizliği).

NEREDE KOLAYLIK SAĞLAR?

  • JSON gövdeleri (REST API istek/yanıt örnekleri, test verisi)
  • SQL sorguları (uygulama içine gömülü uzun sorgular)
  • HTML / XML parçaları (e-posta şablonları, sayfa parçaları)
  • JSON Schema, GraphQL, Regex açıklamaları, çok satırlı log mesajları

ESKİ vs YENİ — JSON Karşılaştırması

ESKİ (Java 12 ve öncesi):

String json =
    "{\n" +
    "    \"ad\": \"Ahmet\",\n" +
    "    \"yas\": 30,\n" +
    "    \"aktif\": true\n" +
    "}";

YENİ (Java 13+ Text Block):

String json = """
        {
            "ad": "Ahmet",
            "yas": 30,
            "aktif": true
        }""";

Görüldüğü gibi \n yok, \" yok, + yok. Metin tam JSON gibi okunuyor.

ESKİ vs YENİ — SQL Karşılaştırması

ESKİ:

String sql =
    "SELECT m.ad, s.tutar " +      // <- satır sonundaki boşluğa dikkat!
    "FROM musteriler m " +
    "JOIN siparisler s ON m.id = s.musteri_id " +
    "WHERE s.tutar > 1000";

Burada en büyük tuzak: satır sonlarına boşluk koymayı unutursanız siparislerWHERE gibi kelimeler yapışır ve sorgu bozulur.

YENİ:

String sql = """
        SELECT m.ad, s.tutar
        FROM musteriler m
        JOIN siparisler s ON m.id = s.musteri_id
        WHERE s.tutar > 1000
        """;

GERÇEK HAYAT ÖRNEĞİ

Bir e-ticaret uygulamasında, sipariş onayı e-postası için HTML şablonu, bir JDBC sorgusu ve bir REST API'ye gönderilecek JSON gövdesi düşünün. Üçü de çok satırlı ve içinde tırnak barındıran metinlerdir. Text Blocks ile bu üç durumun da kodu, neredeyse bir editörden kopyala-yapıştır yapılmış kadar temiz olur. Bu, hem yazma süresini hem hata oranını ciddi şekilde düşürür.

TextBlocksPreview.java dosyasında bu üç durumun (JSON, SQL, HTML) ESKİ/YENİ karşılaştırması, girinti yönetimi ve kaçış dizileri çalışan örneklerle var.

Detaylar (kod örneğinde gösterilir)

  • Incidental whitespace (tesadüfi boşluk): Derleyici, sadece kodu hizalamak için var olan sol boşlukları otomatik siler. Kapanış """ konumu, kaç boşluğun kırpılacağını belirler.
  • \ (satır devamı): Java 14'te geldi. Kaynak kodda satırı bölersiniz ama çıktıda tek satır olur.
  • \s (boşluk koruma): Java 14'te geldi. Sondaki boşlukların kırpılmasını engeller (bir boşluk karakteri yerine geçer).

NOT: \ ve \s Java 13'te YOKTUR; Java 14'te eklenmiştir. TextBlocksPreview.java bu özellikleri kullandığı için en sorunsuz şekilde Java 14+ ile derlenir.


ÖZELLİK 2: Switch Expressions Geliştirmesi — yield (Preview, JEP 354)

NEDİR?

Java 12'de gelen "switch expression" (switch'i bir ifade/değer üreten yapı olarak kullanma) özelliği, Java 13'te güncellendi. Değer döndürmek için kullanılan break <değer>; söz dizimi kaldırıldı, yerine yield anahtar kelimesi getirildi.

NEDEN GELDİ?

Java 12'de bir switch bloğundan değer döndürmek için break 5; gibi bir söz dizimi vardı. Bu kafa karıştırıcıydı çünkü break kelimesi tarihsel olarak "döngüden/ switch'ten çık" anlamına gelir; ona bir de "değer döndür" anlamı yüklemek belirsizdi. Topluluk geri bildirimiyle bu ayrıştırıldı: yield sadece "bu bloğun ürettiği değer budur" demek için kullanılır.

NE İŞE YARAR?

case ... -> ok söz diziminde tek satır yetmediğinde, blok { } açıp içinde hesaplama yapıp yield ile değer döndürmeyi sağlar.

ESKİ vs YENİ

Java 12 (eski preview):

int sonuc = switch (gun) {
    case PAZARTESI, SALI -> 6;
    case CARSAMBA -> {
        int hesap = ...;
        break hesap;   // <- ESKİ: break ile değer döndürme
    }
    default -> 0;
};

Java 13+ (yeni):

int sonuc = switch (gun) {
    case PAZARTESI, SALI -> 6;
    case CARSAMBA -> {
        int hesap = ...;
        yield hesap;   // <- YENİ: yield ile değer döndürme (daha net)
    }
    default -> 0;
};

yield, geleneksel case x: (iki nokta) söz diziminde de kullanılabilir:

int sonuc = switch (gun) {
    case PAZARTESI:
        yield 6;
    default:
        yield 0;
};

GERÇEK HAYAT ÖRNEĞİ

Bir HTTP durum kodunu kullanıcı dostu mesaja çevirirken, bazı durumlar için tek satır (case 404 -> "Bulunamadı"), bazıları için loglama + mesaj üretimi gibi çok adımlı işlem gerekebilir. Çok adımlı durumlarda blok açıp yield ile sonucu döndürürsünüz; kod hem ifade hem deyim avantajını birlikte sunar.

NOT: Bu özellik Java 13'te hâlâ preview'dir; Java 14'te kalıcı olmuştur.


ÖZELLİK 3: Dynamic CDS Archives — Dinamik Sınıf Verisi Paylaşımı (JEP 350)

Sadece kavramsal açıklama (örnek kod dosyası yok).

NEDİR?

CDS (Class Data Sharing), sık kullanılan sınıfların ayrıştırılmış (parse edilmiş) hâlini bir arşiv dosyasına kaydedip, JVM başlatılırken bu arşivi bellek eşlemesiyle (memory-mapping) hızlıca yüklemeyi sağlayan bir tekniktir.

Dynamic CDS, Java 13'ün getirdiği yenilik: arşivi artık uygulamanın çalışması bittiğinde otomatik olarak oluşturabilirsiniz. Eskiden bu süreç çok adımlı ve manueldi (önce sınıf listesi çıkar, sonra arşiv üret).

NEDEN GELDİ / NE İŞE YARAR?

  • Başlatma süresini (startup time) kısaltır. Sınıfları her seferinde diskten okuyup ayrıştırmak yerine, hazır arşivi belleğe eşler.
  • Mikroservis ve serverless gibi sık başlatılan ortamlarda kazanç önemlidir.

NASIL KULLANILIR (kavramsal)

# Uygulama çıkışında dinamik arşiv oluştur:
java -XX:ArchiveClassesAtExit=uygulama.jsa -jar uygulama.jar

# Sonraki çalıştırmalarda arşivi kullan:
java -XX:SharedArchiveFile=uygulama.jsa -jar uygulama.jar

AVANTAJ / RİSK

  • Avantaj: Daha hızlı soğuk başlatma (cold start).
  • Risk: Arşiv, üretildiği classpath'e bağlıdır; classpath değişirse arşiv geçersiz olur ve JVM sessizce arşivsiz devam eder (performans kazancı kaybolur).

ÖZELLİK 4: ZGC — Kullanılmayan Belleği OS'e Geri Verme (JEP 351)

Sadece kavramsal açıklama (örnek kod dosyası yok).

NEDİR?

ZGC (Z Garbage Collector), düşük gecikmeli (low-latency) bir çöp toplayıcıdır. Java 13'te ZGC'ye, kullanmadığı belleği işletim sistemine geri verme (uncommit unused memory) yeteneği eklendi.

NEDEN GELDİ / NE İŞE YARAR?

Eskiden ZGC, bir kez işletim sisteminden aldığı belleği uygulama o belleği kullanmasa bile elinde tutuyordu. Bu, özellikle:

  • Konteyner ortamlarında (bellek limiti olan Docker/Kubernetes pod'ları),
  • Birden çok uygulamanın aynı makineyi paylaştığı senaryolarda

israfa yol açıyordu. Artık ZGC, uzun süre boşta kalan bellek bölgelerini OS'e iade eder; böylece o bellek başka süreçlerce kullanılabilir.

AVANTAJ / RİSK

  • Avantaj: Daha iyi bellek ayak izi (memory footprint), konteynerlerde daha ekonomik kaynak kullanımı.
  • Not: Java 13'te ZGC hâlâ deneyseldi ve yalnızca Linux/x64'te destekleniyordu. Üretim için olgunlaşması sonraki sürümlerde tamamlandı.

Java 12 → Java 13 Geçişinde Ne Değişti? (Özet)

KonuJava 12Java 13
Switch expression değer döndürmebreak <değer>;yield <değer>; (daha net)
Çok satırlı stringYok (string birleştirme + \n)Text Blocks (preview)
CDS arşiviStatik / manuelDinamik (çıkışta otomatik)
ZGC bellek davranışıBelleği elinde tutarBoşta belleği OS'e iade eder

Avantajlar

  • Text Blocks ile JSON/SQL/HTML kodu çok daha okunaklı ve hatasız.
  • yield ile switch ifadeleri anlam olarak netleşti.
  • Daha hızlı başlatma (Dynamic CDS) ve daha az bellek israfı (ZGC).

Dezavantajlar / Riskler

  • Text Blocks ve Switch geliştirmeleri Java 13'te hâlâ PREVIEW'dir. Üretimde kullanmak risklidir; söz dizimi sonraki sürümde değişebilir (nitekim 14'te \ ve \s eklendi).
  • Preview özellikler --enable-preview bayrağı zorunluluğu getirir; bu, build ve dağıtım ayarlarını karmaşıklaştırabilir.
  • Java 13 LTS değildir (6 ay destek). Uzun vadeli projeler için doğrudan 13'e bağlanmak yerine 11 veya 17 gibi LTS sürümler tercih edilmelidir.

Derleme ve Çalıştırma

TextBlocksPreview.java, \ ve \s (Java 14 özellikleri) kullandığı için en sorunsuz şekilde Java 15+ ile preview bayrağı OLMADAN derlenir:

javac TextBlocksPreview.java
java  TextBlocksPreview

Java 13/14 ile preview olarak denemek isterseniz:

javac --enable-preview --release 14 TextBlocksPreview.java
java  --enable-preview TextBlocksPreview

(Java 13'te \ ve \s desteklenmediği için ilgili örnek satırları o sürümde derlenmez; bu kaçış dizileri 14'te eklenmiştir.)

Kod Örnekleri(1)

TextBlocksPreview

çalıştırılabilir
TextBlocksPreview.java
1/*
2 * ============================================================================
3 *  TextBlocksPreview.java
4 * ============================================================================
5 *  Java 13 - TEXT BLOCKS (Önizleme / Preview Özelliği)
6 *
7 *  ÖNEMLİ NOT (Sürüm Bilgisi):
8 *  ---------------------------------------------------------------------------
9 *  - Text Blocks, Java 13'te (Eylül 2019) PREVIEW (önizleme) olarak geldi.
10 *    JEP 355 ile tanıtıldı.
11 *  - Java 14'te ikinci bir preview turu yaşadı (JEP 368). Bu turda \ (satır
12 *    sonu birleştirme) ve \s (boşluk koruma) kaçış dizileri eklendi.
13 *  - Java 15'te KALICI (kararlı/standard) hale geldi (JEP 378).
14 *
15 *  DERLEME TALİMATI:
16 *  ---------------------------------------------------------------------------
17 *  * Java 13 veya 14 ile derliyorsanız, önizleme özelliği açık olmalıdır:
18 *        javac --enable-preview --release 13 TextBlocksPreview.java
19 *        java  --enable-preview TextBlocksPreview
20 *
21 *    (Java 14 için --release 14 kullanın.)
22 *
23 *  * Java 15 ve sonrası ile derliyorsanız, Text Blocks artık KALICI olduğu
24 *    için herhangi bir özel bayrak GEREKMEZ:
25 *        javac TextBlocksPreview.java
26 *        java  TextBlocksPreview
27 *
28 *  Bu dosya, \ ve \s kaçış dizilerini de kullandığı için en sorunsuz şekilde
29 *  Java 15+ ile (preview bayrağı olmadan) derlenir. Java 13'te derlemek
30 *  isterseniz \ ve \s kullanan satırları Java 13'ün desteklemediğini unutmayın
31 *  (bunlar 14'te geldi); o satırlar yorumda ayrıca işaretlenmiştir.
32 * ============================================================================
33 */
34
35public class TextBlocksPreview {
36
37    public static void main(String[] args) {
38
39        System.out.println("=================================================");
40        System.out.println("   JAVA 13 - TEXT BLOCKS (Önizleme) ÖRNEKLERİ");
41        System.out.println("=================================================\n");
42
43        ornek1_JsonYazimi();
44        ornek2_SqlSorgusu();
45        ornek3_HtmlYazimi();
46        ornek4_GirintiYonetimi();
47        ornek5_KacisDizileri();
48        ornek6_GercekHayatRaporu();
49    }
50
51    /* ========================================================================
52     * ÖRNEK 1: JSON YAZIMI
53     * ------------------------------------------------------------------------
54     * PROBLEM: Java'da çok satırlı JSON metnini elle yazmak işkenceydi.
55     * Her satır için tırnak açıp kapatmak, satır sonuna \n koymak, satırları
56     * + ile birleştirmek ve JSON içindeki çift tırnakları \" diye kaçırmak
57     * gerekiyordu. Buna "kaçış karakteri cehennemi" (escape hell) denir.
58     * ====================================================================== */
59    static void ornek1_JsonYazimi() {
60        System.out.println("--- ÖRNEK 1: JSON YAZIMI ---\n");
61
62        /*
63         * ESKİ YÖNTEM (Java 12 ve öncesi):
64         * ---------------------------------
65         * Dikkat edin:
66         *   - Her satır ayrı bir String literal ("...").
67         *   - JSON içindeki her " işareti \" olarak kaçırılmış.
68         *   - Satır sonlarına \n elle eklenmiş.
69         *   - Satırlar + operatörü ile birleştirilmiş.
70         * Bu, okunması ve bakımı çok zor, hataya açık bir koddur.
71         */
72        String eskiJson =
73                "{\n" +
74                "    \"ad\": \"Ahmet\",\n" +
75                "    \"soyad\": \"Yılmaz\",\n" +
76                "    \"yas\": 30,\n" +
77                "    \"adres\": {\n" +
78                "        \"sehir\": \"İstanbul\",\n" +
79                "        \"ulke\": \"Türkiye\"\n" +
80                "    },\n" +
81                "    \"aktif\": true\n" +
82                "}";
83
84        System.out.println(">> ESKİ YÖNTEM (kaçış cehennemi):");
85        System.out.println(eskiJson);
86        System.out.println();
87
88        /*
89         * YENİ YÖNTEM (Java 13+ Text Block):
90         * -----------------------------------
91         * Üç çift tırnak (""") ile başlar ve biter.
92         * Açılış """ işaretinden SONRA mutlaka satır başı (yeni satır) gelmeli.
93         * İçeride:
94         *   - Çift tırnakları kaçırmaya GEREK YOK -> sade " yazabiliriz.
95         *   - Satır sonlarına \n koymaya GEREK YOK -> doğal satır sonları korunur.
96         *   - + ile birleştirmeye GEREK YOK.
97         * Sonuç: JSON metni tam olarak "göründüğü gibi" yazılır.
98         */
99        String yeniJson = """
100                {
101                    "ad": "Ahmet",
102                    "soyad": "Yılmaz",
103                    "yas": 30,
104                    "adres": {
105                        "sehir": "İstanbul",
106                        "ulke": "Türkiye"
107                    },
108                    "aktif": true
109                }""";
110
111        System.out.println(">> YENİ YÖNTEM (Text Block - temiz):");
112        System.out.println(yeniJson);
113        System.out.println();
114    }
115
116    /* ========================================================================
117     * ÖRNEK 2: SQL SORGUSU YAZIMI
118     * ------------------------------------------------------------------------
119     * Gerçek hayatta uygulama kodu içinde uzun SQL sorguları yazmak çok
120     * yaygındır. Eski yöntemde her satırın string birleştirmesi yapılır,
121     * boşluk koymayı unutmak yüzünden kelimeler birbirine yapışır
122     * (örn. "FROMmusteriler" gibi) ve sorgu bozulur.
123     * ====================================================================== */
124    static void ornek2_SqlSorgusu() {
125        System.out.println("--- ÖRNEK 2: SQL SORGUSU YAZIMI ---\n");
126
127        /*
128         * ESKİ YÖNTEM (Java 12 ve öncesi):
129         * Klasik tuzak: satır sonlarındaki boşluklar. "siparisler" ile "WHERE"
130         * arasında boşluk bırakmak için satır sonuna " " eklemek gerekir.
131         * Unutursanız "siparislerWHERE" olur ve sorgu çalışmaz.
132         */
133        String eskiSql =
134                "SELECT m.ad, m.soyad, s.tutar, s.tarih " +
135                "FROM musteriler m " +
136                "INNER JOIN siparisler s ON m.id = s.musteri_id " +
137                "WHERE s.tutar > 1000 " +
138                "  AND s.tarih >= '2024-01-01' " +
139                "ORDER BY s.tutar DESC";
140
141        System.out.println(">> ESKİ YÖNTEM (boşluk tuzaklı string birleştirme):");
142        System.out.println(eskiSql);
143        System.out.println();
144
145        /*
146         * YENİ YÖNTEM (Java 13+ Text Block):
147         * Sorgu tıpkı bir SQL editöründeymiş gibi okunabilir biçimde yazılır.
148         * Boşluk/satır sonu derdi yok. Bakımı çok kolaydır; yeni bir koşul
149         * eklemek için sadece yeni bir satır yazarsınız.
150         */
151        String yeniSql = """
152                SELECT m.ad, m.soyad, s.tutar, s.tarih
153                FROM musteriler m
154                INNER JOIN siparisler s ON m.id = s.musteri_id
155                WHERE s.tutar > 1000
156                  AND s.tarih >= '2024-01-01'
157                ORDER BY s.tutar DESC
158                """;
159
160        System.out.println(">> YENİ YÖNTEM (Text Block - okunaklı SQL):");
161        System.out.println(yeniSql);
162        System.out.println();
163    }
164
165    /* ========================================================================
166     * ÖRNEK 3: HTML YAZIMI
167     * ------------------------------------------------------------------------
168     * HTML içinde hem çift tırnak (attribute'lar: class="...") hem de iç içe
169     * yapı çoktur. Eski yöntemde bu tam bir kabustu.
170     * ====================================================================== */
171    static void ornek3_HtmlYazimi() {
172        System.out.println("--- ÖRNEK 3: HTML YAZIMI ---\n");
173
174        // ESKİ YÖNTEM: tüm tırnaklar \" ile kaçırılmış, çok zor okunur.
175        String eskiHtml =
176                "<html>\n" +
177                "    <body>\n" +
178                "        <h1 class=\"baslik\">Merhaba Dünya</h1>\n" +
179                "        <p id=\"aciklama\">Bu bir <b>Text Block</b> örneğidir.</p>\n" +
180                "    </body>\n" +
181                "</html>";
182
183        System.out.println(">> ESKİ YÖNTEM:");
184        System.out.println(eskiHtml);
185        System.out.println();
186
187        // YENİ YÖNTEM: tırnaklar olduğu gibi, yapı tam HTML gibi görünüyor.
188        String yeniHtml = """
189                <html>
190                    <body>
191                        <h1 class="baslik">Merhaba Dünya</h1>
192                        <p id="aciklama">Bu bir <b>Text Block</b> örneğidir.</p>
193                    </body>
194                </html>""";
195
196        System.out.println(">> YENİ YÖNTEM (Text Block):");
197        System.out.println(yeniHtml);
198        System.out.println();
199    }
200
201    /* ========================================================================
202     * ÖRNEK 4: GİRİNTİ YÖNETİMİ (INCIDENTAL WHITESPACE)
203     * ------------------------------------------------------------------------
204     * Text Block'larda kodun girintisi (sol taraftaki boşluklar) ile metnin
205     * gerçek girintisini ayırmak gerekir. Derleyici, "tesadüfi boşluk"
206     * (incidental whitespace) dediğimiz, sadece kodu hizalamak için var olan
207     * boşlukları otomatik olarak siler.
208     *
209     * KURAL: Tüm satırlar (kapanış """ dahil) içinde EN SOLDA başlayan satır
210     * referans alınır. O satırın solundaki boşluk miktarı kadar boşluk tüm
211     * satırlardan kırpılır. Kapanış """ konumu bu referansı belirlemede
212     * çok etkilidir.
213     * ====================================================================== */
214    static void ornek4_GirintiYonetimi() {
215        System.out.println("--- ÖRNEK 4: GİRİNTİ YÖNETİMİ ---\n");
216
217        /*
218         * Burada kapanış """ işareti, metnin başlamasını istediğimiz sütunda.
219         * Bu yüzden satırların başındaki "kod hizalama" boşlukları silinir,
220         * metin sola dayalı çıkar.
221         */
222        String solaDayali = """
223                Satir 1
224                Satir 2
225                Satir 3
226                """;
227        System.out.println(">> Sola dayalı (incidental whitespace silindi):");
228        System.out.println(solaDayali);
229
230        /*
231         * Şimdi bilerek girinti EKLİYORUZ. Kapanış """ işaretini daha sola
232         * çekersek, ona göre satırların başındaki fazladan boşluklar KORUNUR.
233         * Aşağıda "    Girintili" satırı, kapanış """ ye göre 4 boşluk içeride.
234         */
235        String girintili = """
236                    Girintili satir
237                Normal satir
238                """;
239        System.out.println(">> Bilinçli girinti korundu:");
240        System.out.println(girintili);
241    }
242
243    /* ========================================================================
244     * ÖRNEK 5: KAÇIŞ DİZİLERİ (\ satır devamı ve \s boşluk koruma)
245     * ------------------------------------------------------------------------
246     * DİKKAT: \ (satır birleştirme) ve \s (boşluk koruma) kaçış dizileri
247     * Java 14'te (ikinci preview) eklendi. Java 13'te BU İKİSİ YOKTUR.
248     * Bu yüzden bu örnek en güvenli şekilde Java 14+ ile derlenir.
249     * ====================================================================== */
250    static void ornek5_KacisDizileri() {
251        System.out.println("--- ÖRNEK 5: \\ ve \\s KAÇIŞ DİZİLERİ (Java 14+) ---\n");
252
253        /*
254         * \ (ters bölü + satır sonu): O noktadaki YENİ SATIR karakterini
255         * iptal eder. Yani kaynak kodda satırı bölersiniz ama çıktıda tek
256         * satır olur. Çok uzun tek satırlık metinleri okunaklı yazmak için
257         * idealdir.
258         */
259        String tekSatir = """
260                Bu cumle kaynak kodda \
261                bolundu ama ciktida \
262                tek satir olarak gorunur.""";
263        System.out.println(">> \\ ile satır devamı (çıktıda tek satır):");
264        System.out.println(tekSatir);
265        System.out.println();
266
267        /*
268         * \s: Tam olarak bir boşluk (space) karakterini temsil eder ve
269         * kendisinden önceki sondaki boşlukların (trailing whitespace)
270         * kırpılmasını ENGELLER. Sondaki boşlukların korunması gerektiğinde
271         * (örn. sabit genişlikli sütunlar) kullanılır.
272         */
273        String bosluklar = """
274                Ad     \s
275                Soyad  \s
276                """;
277        System.out.println(">> \\s ile sondaki boşluklar korundu (| ile gösterim):");
278        for (String satir : bosluklar.split("\n")) {
279            System.out.println("|" + satir + "|");
280        }
281        System.out.println();
282    }
283
284    /* ========================================================================
285     * ÖRNEK 6: GERÇEK HAYAT - DİNAMİK RAPOR / E-POSTA ŞABLONU
286     * ------------------------------------------------------------------------
287     * Text Block + String.formatted() (Java 15'te eklendi, formatlı metin için)
288     * birlikte kullanılarak şablonlu çıktı üretmek çok temiz olur.
289     * Burada formatted yerine taşınabilirlik için klasik String.format
290     * kullanıyoruz; ikisi de aynı işi yapar.
291     * ====================================================================== */
292    static void ornek6_GercekHayatRaporu() {
293        System.out.println("--- ÖRNEK 6: GERÇEK HAYAT - E-POSTA ŞABLONU ---\n");
294
295        String musteriAdi = "Zeynep Kaya";
296        String siparisNo = "SP-2024-00917";
297        double tutar = 1499.90;
298
299        String sablon = """
300                Sayın %s,
301
302                %s numaralı siparişiniz başarıyla alınmıştır.
303                Toplam tutar: %.2f TL
304
305                Bizi tercih ettiğiniz için teşekkür ederiz.
306                İyi günler dileriz.
307
308                ABC Mağazacılık A.Ş.
309                """;
310
311        String email = String.format(sablon, musteriAdi, siparisNo, tutar);
312
313        System.out.println(">> Üretilen e-posta:");
314        System.out.println(email);
315    }
316}
Çıktı yerel JDK 21 ile yakalandı — tarayıcıda JVM çalışmaz.