Eğitim Portalı/Sürüm Analizi/Java 17 (Eylül 2021) — LTS — Detaylı Türkçe Dokümantasyon
Sürüm Analizi05-java-versiyon-analizi/10-Java-17

Java 17 (Eylül 2021) — LTS — Detaylı Türkçe Dokümantasyon

> Java 17, Java 8 ve Java 11'den sonra kurumsal dünyanın en çok hedeflediği > LTS sürümüdür. Bu klasör, bu repo'nun EN DETAYLI bölümüdür.

Java 17 (Eylül 2021) — LTS — Detaylı Türkçe Dokümantasyon

Java 17, Java 8 ve Java 11'den sonra kurumsal dünyanın en çok hedeflediği LTS sürümüdür. Bu klasör, bu repo'nun EN DETAYLI bölümüdür.

Sürüm Bilgisi

ÖzellikDeğer
SürümJava SE 17 / JDK 17
Çıkış Tarihi14 Eylül 2021
LTS mi?EVET — Long-Term Support (Uzun Süreli Destek)
Destek TakvimiOracle premier destek ~2026, genişletilmiş destek ~2029'a kadar (dağıtıma göre değişir). OpenJDK dağıtımları (Adoptium/Temurin, Amazon Corretto, Azul, Red Hat) genellikle 2027-2029+ destek sunar.
Önceki LTSJava 11 (2018), Java 8 (2014)
Sonraki LTSJava 21 (2023)

LTS Neden Bu Kadar Önemli? (Kurumsal Bakış)

LTS (Long-Term Support) sürümleri, çok yıllı güvenlik yamaları ve hata düzeltmeleri alır. Kurumlar üretim sistemlerini LTS sürümleri üzerine kurar çünkü:

  1. Uzun destek penceresi: Her 6 ayda bir sürüm yükseltmek zorunda kalmazsınız.
  2. Üretim standardı: Üçüncü parti kütüphaneler, framework'ler (Spring Boot 3.x, Jakarta EE 10) ve bulut sağlayıcılar baseline olarak Java 17'yi hedefler.
    • Spring Boot 3.x, MİNİMUM Java 17 gerektirir — bu tek başına devasa bir kurumsal geçiş dalgası yaratmıştır.
  3. Güvenlik: Uzun süre CVE yamaları gelir.
  4. Kararlılık: Java 9-16 arasında biriken tüm modern özellikler (records, sealed, pattern matching, switch expressions, text blocks, var, NPE mesajları) tek, kararlı ve desteklenen bir pakette toplanır.

Sonuç: Java 8/11'de kalmış kurumlar için bir sonraki doğal durak Java 17'dir.


Genel Bakış — Bu Sürümde Neler Var?

ÖzellikDurumDosya
Sealed ClassesKALICI (JEP 409)SealedClassesKalici.java
Pattern Matching for switchPreview (JEP 406)PatternMatchingSwitch.java
Records + Sealed + Pattern (ADT)BirleşimCebirselVeriTipleri.java
Enhanced Pseudo-Random GeneratorsKALICI (JEP 356)RandomGenerator.java
Yeni macOS Rendering PipelineKalıcı (JEP 382)
macOS/AArch64 PortuKalıcı (JEP 391)
Applet API'nin kaldırılmaya hazırlanmasıDeprecation (JEP 398)
Security Manager deprecationDeprecation (JEP 411)
Strong Encapsulation (varsayılan)Kalıcı (JEP 403)
Foreign Function & Memory APIIncubator (JEP 412)
Vector APIIncubator (JEP 414)

1) Sealed Classes (Mühürlü Sınıflar) — KALICI (JEP 409)

Dosya: SealedClassesKalici.java

NEDİR?

Bir sınıf/arayüzün, KENDİSİNDEN HANGİ sınıfların türeyebileceğini permits ile açıkça kısıtlamasıdır.

NEDEN GELDİ?

Java'da bir tip ya final (kimse türetemez) ya da tamamen açıktı. Arada "sadece şu belirli sınıflar türesin" seçeneği yoktu. Sealed bunu sağlar.

Anahtar Kelimeler

  • sealed — mühürlü; alt tipleri permits ile sınırlar
  • permits — izinli alt tipleri listeler (aynı dosyadaysa çıkarılabilir)
  • final — alt tip artık kapalı (yaprak)
  • non-sealed — mührü tekrar AÇAR (o daldan herkes türeyebilir)

Kural: Mühürlü bir tipin her izinli alt tipi final, sealed veya non-sealed olmak ZORUNDADIR. record'lar örtük final olduğu için mühürlü hiyerarşilerde mükemmel yapraktır.

ESKİ vs YENİ

// ESKİ: ya tamamen final ya tamamen açık; "sadece şunlar türesin" diyemezdik
public abstract class Sekil { }   // herkes türetebilir, kontrol yok

// YENİ: kontrollü, kapalı hiyerarşi
public sealed interface Sekil permits Daire, Kare, Dikdortgen { }

GÜCÜ NEREDE? — Pattern Matching ile Exhaustiveness

Alt tip kümesi sonlu ve bilinir olduğu için, switch tüm alt tipleri kapsadığında derleyici default dalı İSTEMEZ ve eksik dal varsa derleme hatası verir.

Gerçek Hayat

Durum makineleri, ödeme yöntemleri, mesaj tipleri, AST düğümleri.


2) Pattern Matching for switch — Preview (JEP 406)

Dosya: PatternMatchingSwitch.java

Java 17'de PREVIEW'dir. Derleme/çalıştırma bayrakları gerekir:

javac --release 17 --enable-preview PatternMatchingSwitch.java
java  --enable-preview PatternMatchingSwitch

(Özellik Java 21'de kalıcı oldu.)

NEDİR?

switch'in artık sabit değerler yerine bir nesnenin tipine göre dallanabilmesi: case String s ->.

ESKİ vs YENİ

// ESKİ: uzun if-else-if instanceof zinciri
if (o instanceof Integer i) { ... }
else if (o instanceof String s) { ... }

// YENİ: sade, okunabilir switch
switch (o) {
    case Integer i -> ...;
    case String s  -> ...;
    default        -> ...;
}

Ek Yetenekler

  • Guarded pattern: case Integer i when i < 10 -> (tip + ek koşul)
  • null güvenliği: case null -> (artık switch null'da NPE atmaz)

3) Records + Sealed + Pattern Matching = CEBİRSEL VERİ TİPLERİ — Modern Java'nın Kalbi

Dosya: CebirselVeriTipleri.java

Bu dosya bu repo'nun en önemli örneğidir. --enable-preview gerektirir (switch pattern matching kullanır).

NEDİR? (Algebraic Data Types / ADT)

  • SEALED = "sum type": tip, sonlu varyantların toplamıdır (Sekil = Daire | Kare | Ucgen)
  • RECORD = "product type": her varyantın alanları (Nokta = x VE y)
  • PATTERN MATCHING = varyantlara göre güvenli, eksiksiz dallanma

NEDEN DEVRİMSEL? (Kurumsal Güvenlik)

  1. Geçersiz durumlar temsil edilemez hale gelir → tip güvenliği.
  2. Exhaustiveness: Yeni bir varyant eklediğinizde, onu işlemeyen HER switch derleme hatası verir. "Bir yeri güncellemeyi unuttum" hatası imkânsız olur.
  3. Domain'i kodda neredeyse doğal dil gibi ifade edersiniz.

Dosyadaki Gerçek Hayat Senaryoları

  • A) Ödeme sistemi: Odeme = KrediKarti | Havale | KapidaOdeme; her tipin farklı komisyon kuralı (exhaustiveness ile güvenli).
  • B) Geometrik şekiller: alan/çevre hesabı (Heron formülü dahil).
  • C) JSON düğüm tipleri: Json = JNull | JBool | JSayi | JMetin | JDizi | JObje — özyinelemeli (recursive) serileştirme.
  • Bonus) Result tipi: Sonuc = Basari | Hata — exception yerine tip olarak hata yönetimi.

Klasik OOP vs ADT (Expression Problem)

  • Klasik OOP: yeni alt tip eklemek kolay, yeni işlem eklemek zor.
  • ADT + switch: yeni işlem eklemek kolay; yeni varyant eklediğinizde derleyici eksik switch'leri yakalar.

4) Enhanced Pseudo-Random Number Generators — KALICI (JEP 356)

Dosya: RandomGenerator.java

NEDİR / NEDEN GELDİ?

java.util.random.RandomGenerator ortak arayüzü altında tüm rastgele üreticileri toplar. RandomGeneratorFactory ile algoritmayı isimle seçebilirsiniz (örn. L64X128MixRandom). Eski java.util.Random tek, zayıf bir LCG algoritmasıyla sınırlıydı; değiştirilebilir (pluggable) değildi.

ESKİ vs YENİ

// ESKİ
var r = new java.util.Random();
// YENİ - algoritma seçilebilir
RandomGenerator g = RandomGeneratorFactory.of("L64X128MixRandom").create();

Gerçek Hayat Notu

  • Güvenlik (token/şifre/anahtar) için daima SecureRandom.
  • Paralel simülasyonlarda splittable/jumpable üreticiler.

5) Yeni macOS Rendering Pipeline (JEP 382) ve macOS/AArch64 Portu (JEP 391)

  • JEP 382: Eski OpenGL temelli Java 2D pipeline'ı, Apple'ın yeni Metal API'sine taşındı (OpenGL macOS'ta deprecated edildiği için). Daha iyi grafik performansı ve geleceğe uyum.
  • JEP 391: Java, Apple Silicon (M1/M2 — AArch64) üzerinde yerel olarak çalışır. Apple donanımındaki geliştiriciler/sunucular için yüksek performans ve enerji verimliliği.

6) Deprecation / Kaldırma — GEÇİŞ RİSKİ

  • Applet API (JEP 398): Kaldırılmak üzere işaretlendi. Tarayıcılar zaten plugin'i bıraktığından pratikte ölü teknoloji. Eski applet kodu varsa modernleştirin.
  • Security Manager (JEP 411): SecurityManager kaldırılmak üzere deprecate edildi. Güvenlik politikalarını SecurityManager'a dayandıran (eski) kodlar gelecekte bozulacak; alternatif izolasyon mekanizmalarına (konteyner, modül sistemi) geçilmesi önerilir.

7) Strong Encapsulation Varsayılan Açık (JEP 403)

JDK iç API'lerine (sun.*, dahili paketler) reflection erişimi artık varsayılan olarak kapalı ve --illegal-access ile açılamaz (bayrak etkisiz). Yalnızca --add-opens/--add-exports ile noktasal açılabilir.

  • Risk: İç API'lere dayanan ÇOK ESKİ kütüphaneler kırılabilir.
  • Çözüm: Bağımlılıkları güncelleyin; geçici olarak --add-opens kullanın.

Java 8 / 11'den Java 17'ye Geçiş Rehberi

Avantajlar

  • LTS güvencesi + uzun destek.
  • Spring Boot 3.x, modern framework'ler ve bulut platformları için baseline.
  • 9-16 arası tüm modern dil özellikleri tek kararlı pakette.
  • Daha iyi GC (ZGC/Shenandoah olgunlaştı), daha iyi container farkındalığı, daha iyi performans.

Riskler ve Dikkat Edilecekler

  1. Strong encapsulation: İç API'lere dayanan eski kütüphaneler kırılabilir → bağımlılıkları güncelleyin, gerekirse --add-opens.
  2. Kaldırılan/değişen API'ler: Java 8 → 11 geçişinde javax.xml.bind (JAXB), java.activation, CORBA gibi paketler JDK'dan çıkarılmıştı; bunları ayrı bağımlılık olarak ekleyin.
  3. Security Manager kullanan kod → alternatif izolasyona geçin.
  4. Applet kullanan kod → modernleştirin.
  5. Derleme bayrakları: --release 17 ile derleyin; tüm bağımlılıkların Java 17 uyumlu sürümlerine yükseltin.

Önerilen Geçiş Adımları

  1. Önce Java 11'e geçin (ara durak), sonra Java 17.
  2. Tüm bağımlılıkları en güncel sürümlere çıkarın.
  3. jdeps ile iç API kullanımını analiz edin.
  4. Test ortamında preview/deprecation uyarılarını giderin.
  5. Üretim öncesi performans ve GC profilini doğrulayın.

Bu Klasördeki Dosyalar ve Derleme

DosyaPreview gerekir mi?
SealedClassesKalici.javaHayır
RandomGenerator.javaHayır
PatternMatchingSwitch.javaEvet
CebirselVeriTipleri.javaEvet
# Preview gerektirmeyenler
javac SealedClassesKalici.java && java SealedClassesKalici
javac RandomGenerator.java     && java RandomGenerator

# Preview gerektirenler (switch pattern matching - Java 17)
javac --release 17 --enable-preview PatternMatchingSwitch.java
java  --enable-preview PatternMatchingSwitch

javac --release 17 --enable-preview CebirselVeriTipleri.java
java  --enable-preview CebirselVeriTipleri

Kod Örnekleri(4)

CebirselVeriTipleri

çalıştırılabilir
CebirselVeriTipleri.java
1// =============================================================================
2//  CebirselVeriTipleri.java
3//  JAVA 17 (LTS) - Records + Sealed + Pattern Matching = ALGEBRAIC DATA TYPES
4//  (Cebirsel Veri Tipleri) - MODERN JAVA'NIN KALBİ
5// =============================================================================
6//
7//  !!! Bu dosya, switch pattern matching (Java 17 PREVIEW) kullanır. Derlerken:
8//
9//      javac --release 17 --enable-preview CebirselVeriTipleri.java
10//      java  --enable-preview CebirselVeriTipleri
11//
12//  NEDİR? — CEBİRSEL VERİ TİPLERİ (ADT)
13//  Fonksiyonel dillerde (Haskell, Scala, Rust...) çok güçlü bir modelleme aracı
14//  vardır: bir tip, sonlu sayıda "varyant"ın TOPLAMI olarak tanımlanır.
15//    Sekil = Daire | Kare | Dikdortgen           ("ya o ya bu" -> sum type)
16//    Nokta = (x VE y)                             ("hem o hem bu" -> product type)
17//  Java 17'de bu modeli üç özellikle birebir kurarız:
18//    - SEALED  : tipin SONLU varyant kümesini tanımlar (sum type)
19//    - RECORD  : her varyantın alanlarını taşır (product type)
20//    - PATTERN MATCHING (switch) : varyantlara göre güvenli dallanma
21//
22//  NEDEN BU KADAR ÖNEMLİ / GÜCÜ NEREDE?
23//   1) TİP GÜVENLİĞİ: Geçersiz durumlar TEMSİL EDİLEMEZ hale gelir.
24//   2) EKSİKSİZLİK (exhaustiveness): Yeni bir varyant eklediğinizde, onu
25//      işlemeyen her switch DERLEME HATASI verir. "Bir yeri güncellemeyi
26//      unutma" hatası ortadan kalkar. Bu, bakım açısından devrimseldir.
27//   3) OKUNABİLİRLİK: Domain'i kodda neredeyse İngilizce/Türkçe gibi ifade ederiz.
28//
29//  Aşağıda 3 GERÇEK HAYAT senaryosu var:
30//   A) Ödeme yöntemleri (ödeme sistemi)
31//   B) Geometrik şekiller (alan/çevre hesabı)
32//   C) JSON düğüm tipleri (parser/serializer)
33//   + Bonus: Result tipi (Basari | Hata) — fonksiyonel hata yönetimi
34// =============================================================================
35
36import java.util.List;
37import java.util.Map;
38
39public class CebirselVeriTipleri {
40
41    public static void main(String[] args) {
42
43        System.out.println("=== JAVA 17 (LTS): CEBİRSEL VERİ TİPLERİ (Records+Sealed+Pattern) ===\n");
44
45        // =====================================================================
46        //  SENARYO A: ÖDEME SİSTEMİ
47        //  Bir ödeme YA kredi kartı, YA havale, YA da kapıda ödeme olabilir.
48        //  Her birinin FARKLI alanları (ve farklı komisyonu) vardır.
49        // =====================================================================
50        System.out.println("####### SENARYO A: ÖDEME SİSTEMİ #######");
51        List<Odeme> odemeler = List.of(
52                new KrediKarti("4111111111111111", 250.0),
53                new Havale("TR12 0001 ...", 1000.0),
54                new KapidaOdeme(150.0, true)
55        );
56        for (Odeme o : odemeler) {
57            System.out.printf("  %-12s | tutar=%.2f | komisyon=%.2f | %s%n",
58                    o.getClass().getSimpleName(),
59                    tutar(o), komisyon(o), aciklama(o));
60        }
61        System.out.println();
62
63        // =====================================================================
64        //  SENARYO B: GEOMETRİK ŞEKİLLER
65        // =====================================================================
66        System.out.println("####### SENARYO B: GEOMETRİK ŞEKİLLER #######");
67        List<Sekil> sekiller = List.of(
68                new Daire(5),
69                new Kare(4),
70                new Ucgen(3, 4, 5)
71        );
72        for (Sekil s : sekiller) {
73            System.out.printf("  %-12s | alan=%.2f | çevre=%.2f%n",
74                    s.getClass().getSimpleName(), alan(s), cevre(s));
75        }
76        System.out.println();
77
78        // =====================================================================
79        //  SENARYO C: JSON DÜĞÜM TİPLERİ
80        //  Bir JSON değeri: null | boolean | sayı | metin | dizi | nesne
81        //  Bu, ADT için klasik bir örnektir (özyinelemeli/recursive yapı).
82        // =====================================================================
83        System.out.println("####### SENARYO C: JSON SERILEŞTIRME #######");
84        Json belge = new JObje(Map.of(
85                "ad", new JMetin("Ahmet"),
86                "yas", new JSayi(30),
87                "aktif", new JBool(true),
88                "roller", new JDizi(List.of(new JMetin("admin"), new JMetin("editor")))
89        ));
90        System.out.println("  JSON çıktısı:");
91        System.out.println("  " + json(belge));
92        System.out.println();
93
94        // =====================================================================
95        //  BONUS: RESULT TİPİ (Basari | Hata) - fonksiyonel hata yönetimi
96        //  Exception fırlatmak yerine, sonucu TİP olarak döndürürüz.
97        // =====================================================================
98        System.out.println("####### BONUS: RESULT TİPİ (hata yönetimi) #######");
99        System.out.println("  10 / 2 = " + sonucMetni(bol(10, 2)));
100        System.out.println("  10 / 0 = " + sonucMetni(bol(10, 0)));
101        System.out.println();
102
103        System.out.println("=== Yeni bir varyant eklerseniz, ilgili her switch DERLEME HATASI verir. ===");
104        System.out.println("=== İşte bu yüzden ADT'ler kurumsal kodda devasa bir güvenlik sağlar. ===");
105    }
106
107    // =========================================================================
108    //  A) ÖDEME — sealed hiyerarşi + record varyantlar
109    // =========================================================================
110    sealed interface Odeme permits KrediKarti, Havale, KapidaOdeme {}
111    record KrediKarti(String kartNo, double tutar) implements Odeme {}
112    record Havale(String iban, double tutar) implements Odeme {}
113    record KapidaOdeme(double tutar, boolean nakit) implements Odeme {}
114
115    // switch pattern matching ile tutar çıkarımı (record deconstruction yerine
116    // basit alan erişimi; Java 17 preview record pattern içermez, o Java 21'dedir)
117    static double tutar(Odeme o) {
118        return switch (o) {
119            case KrediKarti k -> k.tutar();
120            case Havale h     -> h.tutar();
121            case KapidaOdeme p-> p.tutar();
122        };
123    }
124
125    // Her ödeme tipinin farklı komisyon kuralı — exhaustiveness sayesinde
126    // bir tipi unutursak derleyici uyarır.
127    static double komisyon(Odeme o) {
128        return switch (o) {
129            case KrediKarti k -> k.tutar() * 0.02;   // %2
130            case Havale h     -> 0.0;                 // ücretsiz
131            case KapidaOdeme p -> p.nakit() ? 0.0 : 5.0; // kartla kapıda +5
132        };
133    }
134
135    static String aciklama(Odeme o) {
136        return switch (o) {
137            case KrediKarti k -> "Kart **** " + k.kartNo().substring(k.kartNo().length() - 4);
138            case Havale h     -> "IBAN: " + h.iban();
139            case KapidaOdeme p -> p.nakit() ? "Kapıda nakit" : "Kapıda kart";
140        };
141    }
142
143    // =========================================================================
144    //  B) GEOMETRİK ŞEKİLLER
145    // =========================================================================
146    sealed interface Sekil permits Daire, Kare, Ucgen {}
147    record Daire(double r) implements Sekil {}
148    record Kare(double kenar) implements Sekil {}
149    record Ucgen(double a, double b, double c) implements Sekil {}
150
151    static double alan(Sekil s) {
152        return switch (s) {
153            case Daire d -> Math.PI * d.r() * d.r();
154            case Kare k  -> k.kenar() * k.kenar();
155            case Ucgen u -> {
156                double yp = (u.a() + u.b() + u.c()) / 2; // yarı çevre
157                yield Math.sqrt(yp * (yp - u.a()) * (yp - u.b()) * (yp - u.c())); // Heron
158            }
159        };
160    }
161
162    static double cevre(Sekil s) {
163        return switch (s) {
164            case Daire d -> 2 * Math.PI * d.r();
165            case Kare k  -> 4 * k.kenar();
166            case Ucgen u -> u.a() + u.b() + u.c();
167        };
168    }
169
170    // =========================================================================
171    //  C) JSON — özyinelemeli (recursive) ADT
172    // =========================================================================
173    sealed interface Json permits JNull, JBool, JSayi, JMetin, JDizi, JObje {}
174    record JNull() implements Json {}
175    record JBool(boolean deger) implements Json {}
176    record JSayi(double deger) implements Json {}
177    record JMetin(String deger) implements Json {}
178    record JDizi(List<Json> elemanlar) implements Json {}
179    record JObje(Map<String, Json> alanlar) implements Json {}
180
181    // Özyinelemeli serileştirme — switch + pattern matching ile temiz çözüm
182    static String json(Json j) {
183        return switch (j) {
184            case JNull n  -> "null";
185            case JBool b  -> Boolean.toString(b.deger());
186            case JSayi s  -> (s.deger() == Math.floor(s.deger()))
187                    ? Long.toString((long) s.deger())
188                    : Double.toString(s.deger());
189            case JMetin m -> "\"" + m.deger() + "\"";
190            case JDizi d  -> {
191                StringBuilder sb = new StringBuilder("[");
192                for (int i = 0; i < d.elemanlar().size(); i++) {
193                    if (i > 0) sb.append(",");
194                    sb.append(json(d.elemanlar().get(i)));
195                }
196                yield sb.append("]").toString();
197            }
198            case JObje o  -> {
199                StringBuilder sb = new StringBuilder("{");
200                boolean ilk = true;
201                for (var e : o.alanlar().entrySet()) {
202                    if (!ilk) sb.append(",");
203                    sb.append("\"").append(e.getKey()).append("\":").append(json(e.getValue()));
204                    ilk = false;
205                }
206                yield sb.append("}").toString();
207            }
208        };
209    }
210
211    // =========================================================================
212    //  BONUS) RESULT TİPİ: Basari | Hata
213    //  Fonksiyonel hata yönetimi: exception yerine sonucu tip olarak döndür.
214    // =========================================================================
215    sealed interface Sonuc permits Basari, Hata {}
216    record Basari(int deger) implements Sonuc {}
217    record Hata(String mesaj) implements Sonuc {}
218
219    static Sonuc bol(int a, int b) {
220        if (b == 0) return new Hata("Sıfıra bölme!");
221        return new Basari(a / b);
222    }
223
224    static String sonucMetni(Sonuc s) {
225        return switch (s) {
226            case Basari b -> "Başarılı: " + b.deger();
227            case Hata h   -> "Hata: " + h.mesaj();
228        };
229    }
230}
231
232// =============================================================================
233//  NEDEN ADT'LER KURUMSAL KODDA KRİTİK?
234//
235//  Klasik OOP'de "yeni bir alt tip ekleme" kolaydır ama "yeni bir işlem ekleme"
236//  zordur (her sınıfa metot eklenir). ADT + switch yaklaşımında "yeni işlem
237//  ekleme" kolaydır (yeni bir switch metodu yazılır) ve EN ÖNEMLİSİ: yeni bir
238//  VARYANT eklediğinizde, onu işlemeyen TÜM switch'ler DERLEME ZAMANINDA hata
239//  verir. Yani "bir yeri güncellemeyi unutma" sınıfı hatalar imkânsız olur.
240//
241//  Bu yüzden ödeme sistemleri, durum makineleri, parser'lar, kural motorları
242//  gibi "sonlu ama net varyantlı" domainlerde Records+Sealed+Pattern üçlüsü
243//  modern Java'nın en güçlü tasarım aracıdır.
244// =============================================================================
Çıktı yerel JDK 21 ile yakalandı — tarayıcıda JVM çalışmaz.

PatternMatchingSwitch

çalıştırılabilir
PatternMatchingSwitch.java
1// =============================================================================
2//  PatternMatchingSwitch.java
3//  JAVA 17 (LTS) - Pattern Matching for switch (JEP 406) - PREVIEW
4// =============================================================================
5//
6//  !!! ÖNEMLİ: Bu özellik Java 17'de PREVIEW'dir. Derlerken/çalıştırırken
7//  preview bayrakları GEREKİR:
8//
9//      javac --release 17 --enable-preview PatternMatchingSwitch.java
10//      java  --enable-preview PatternMatchingSwitch
11//
12//  (Özellik Java 21'de KALICI oldu. Java 17 LTS ile öğrenirken bu kalıbı
13//   önizleme olarak görüyoruz; üretimde Java 21'e geçince bayrak gerekmez.)
14//
15//  NEDİR?
16//  switch ifadesinde artık SADECE sabit değerlere (int, String, enum) değil,
17//  bir nesnenin TİPİNE göre de dallanabiliyoruz. instanceof pattern matching'in
18//  switch'e taşınmış halidir: "case Tip degisken ->" şeklinde.
19//
20//  NEDEN GELDİ / GÜCÜ NEREDE?
21//  Uzun if-else-if instanceof zincirleri yerine SADE, OKUNABİLİR ve EKSİKSİZLİK
22//  (exhaustiveness) doğrulaması yapılabilen switch yazarız. Sealed tiplerle
23//  birleşince derleyici TÜM olası tiplerin ele alındığını GARANTİ eder.
24//
25//  ÜÇLÜ GÜÇ: sealed + switch + pattern matching
26//   - sealed: alt tipler sonlu ve bilinir
27//   - switch pattern matching: tipe göre dallan
28//   - exhaustiveness: derleyici eksik dalı YAKALAR (default gerekmeyebilir)
29// =============================================================================
30
31public class PatternMatchingSwitch {
32
33    public static void main(String[] args) {
34
35        System.out.println("=== JAVA 17 (LTS): Pattern Matching for switch (preview) ===\n");
36
37        // ---------------------------------------------------------------------
38        // 1) ESKİ if-else-if instanceof zinciri vs YENİ switch
39        // ---------------------------------------------------------------------
40        Object[] veriler = { "metin", 42, 3.14, 100L, "Java" };
41
42        System.out.println("--- 1) ESKİ yöntem (if-else-if) ---");
43        for (Object o : veriler) {
44            System.out.println("  " + bicimlendirEski(o));
45        }
46
47        System.out.println("--- 1) YENİ yöntem (switch pattern matching) ---");
48        for (Object o : veriler) {
49            System.out.println("  " + bicimlendirYeni(o));
50        }
51        System.out.println();
52
53        // ---------------------------------------------------------------------
54        // 2) GUARDED PATTERN: "case Tip g when koşul ->" (ek koşul)
55        //    (Java 17 preview'de bu sözdizimi "case Tip g && koşul" idi;
56        //     standartlaşırken "when" anahtar kelimesi benimsendi. Burada
57        //     Java 17+ ile uyumlu olması için 'when' kullanıyoruz.)
58        // ---------------------------------------------------------------------
59        System.out.println("--- 2) Guarded pattern (when ile koşullu dal) ---");
60        for (Object o : new Object[] { 5, 50, 500, -3 }) {
61            System.out.println("  " + buyuklukSinifi(o));
62        }
63        System.out.println();
64
65        // ---------------------------------------------------------------------
66        // 3) null'ın switch içinde ele alınması
67        //    Eskiden switch'e null gelirse NPE atardı; artık "case null" yazılabilir.
68        // ---------------------------------------------------------------------
69        System.out.println("--- 3) null güvenli switch ---");
70        System.out.println("  " + nullGuvenli("dolu"));
71        System.out.println("  " + nullGuvenli(null));
72        System.out.println();
73
74        // ---------------------------------------------------------------------
75        // 4) GERÇEK HAYAT: sealed tip + switch ile EKSİKSİZ sınıflandırma
76        // ---------------------------------------------------------------------
77        System.out.println("--- 4) Gerçek hayat: sealed Trafik + switch ---");
78        Trafik[] durumlar = { new Kirmizi(), new Sari(2), new Yesil() };
79        for (Trafik t : durumlar) {
80            System.out.println("  " + komut(t));
81        }
82    }
83
84    // ESKİ: tip kontrolleri için uzun if-else-if
85    static String bicimlendirEski(Object o) {
86        if (o instanceof Integer i) {
87            return "int: " + i;
88        } else if (o instanceof Long l) {
89            return "long: " + l;
90        } else if (o instanceof Double d) {
91            return "double: " + d;
92        } else if (o instanceof String s) {
93            return "String(" + s.length() + "): " + s;
94        } else {
95            return "bilinmeyen";
96        }
97    }
98
99    // YENİ: switch pattern matching - daha sade ve okunabilir
100    static String bicimlendirYeni(Object o) {
101        return switch (o) {
102            case Integer i -> "int: " + i;
103            case Long l    -> "long: " + l;
104            case Double d  -> "double: " + d;
105            case String s  -> "String(" + s.length() + "): " + s;
106            default        -> "bilinmeyen";
107        };
108    }
109
110    // Guarded pattern: aynı tip için ek koşullara göre dallanma
111    static String buyuklukSinifi(Object o) {
112        return switch (o) {
113            case Integer i when i < 0   -> i + " -> negatif";
114            case Integer i when i < 10  -> i + " -> küçük";
115            case Integer i when i < 100 -> i + " -> orta";
116            case Integer i             -> i + " -> büyük";
117            default                    -> "sayı değil";
118        };
119    }
120
121    // null güvenli switch
122    static String nullGuvenli(String s) {
123        return switch (s) {
124            case null     -> "değer yok (null)";
125            case "dolu"   -> "dolu değer";
126            default       -> "diğer: " + s;
127        };
128    }
129
130    // -------------------------------------------------------------------------
131    //  GERÇEK HAYAT: trafik ışığı durum makinesi (sealed + switch)
132    // -------------------------------------------------------------------------
133    sealed interface Trafik permits Kirmizi, Sari, Yesil {}
134    record Kirmizi() implements Trafik {}
135    record Sari(int kalanSaniye) implements Trafik {}
136    record Yesil() implements Trafik {}
137
138    // sealed olduğu için switch EKSİKSİZ; default gerekmez (derleyici doğrular)
139    static String komut(Trafik t) {
140        return switch (t) {
141            case Kirmizi k       -> "DUR";
142            case Sari s          -> "HAZIRLAN (" + s.kalanSaniye() + " sn)";
143            case Yesil y         -> "GEÇ";
144        };
145    }
146}
Çıktı yerel JDK 21 ile yakalandı — tarayıcıda JVM çalışmaz.

RandomGenerator

çalıştırılabilir
RandomGenerator.java
1// =============================================================================
2//  RandomGenerator.java
3//  JAVA 17 (LTS) - Enhanced Pseudo-Random Number Generators (JEP 356)
4// =============================================================================
5//
6//  NEDİR?
7//  Java 17, rastgele sayı üreticileri için yeni ve ortak bir arayüz ailesi
8//  getirdi: java.util.random.RandomGenerator. Artık Random, SecureRandom,
9//  SplittableRandom ve yeni algoritmalar (LXM, Xoshiro/Xoroshiro ailesi) hepsi
10//  ORTAK bir arayüz altında toplandı.
11//
12//  NEDEN GELDİ?
13//  Eski java.util.Random:
14//    - Tek bir (zayıf) algoritma sunuyordu (LCG - lineer kongrüent).
15//    - Farklı algoritmaları kolayca değiştirmek (pluggable) mümkün değildi.
16//    - Stream tabanlı, paralel/bölünebilir (splittable) üretim için tutarlı bir
17//      soyutlama yoktu.
18//  Yeni RandomGeneratorFactory ile algoritmayı İSME GÖRE seçebilir, ortak
19//  arayüz üzerinden kullanabiliriz.
20//
21//  NOT: Dosyadaki public sınıf adının dosya adıyla eşleşmesi gerekir; bu yüzden
22//  public sınıf adı "RandomGenerator"dır. JDK arayüzü olan
23//  java.util.random.RandomGenerator'a karışmaması için onu TAM NİTELİKLİ
24//  (fully-qualified) isimle kullanıyoruz; ayrı bir import YAPMIYORUZ.
25//
26//  Derlemek için: javac RandomGenerator.java
27//  Çalıştırmak  : java RandomGenerator
28// =============================================================================
29
30import java.util.random.RandomGeneratorFactory;
31import java.util.stream.Collectors;
32
33public class RandomGenerator {
34
35    public static void main(String[] args) {
36
37        System.out.println("=== JAVA 17 (LTS): Enhanced Random Number Generators ===\n");
38
39        // ---------------------------------------------------------------------
40        // 1) ESKİ YÖNTEM: java.util.Random (hâlâ çalışır, ama tek algoritma)
41        // ---------------------------------------------------------------------
42        System.out.println("--- 1) ESKİ: java.util.Random ---");
43        var eski = new java.util.Random(42); // sabit tohum -> tekrarlanabilir
44        System.out.println("  Eski Random ilk 3 değer: "
45                + eski.nextInt(100) + ", " + eski.nextInt(100) + ", " + eski.nextInt(100));
46        System.out.println();
47
48        // ---------------------------------------------------------------------
49        // 2) YENİ: RandomGenerator arayüzü üzerinden, algoritma SEÇİLEBİLİR
50        // ---------------------------------------------------------------------
51        System.out.println("--- 2) YENİ: RandomGeneratorFactory ile algoritma seçimi ---");
52        // "L64X128MixRandom" modern, kaliteli bir LXM üreticisidir.
53        java.util.random.RandomGenerator modern = RandomGeneratorFactory
54                .of("L64X128MixRandom")
55                .create(42);
56        System.out.println("  Modern üreticinin ilk 3 değeri: "
57                + modern.nextInt(100) + ", " + modern.nextInt(100) + ", " + modern.nextInt(100));
58        System.out.println();
59
60        // ---------------------------------------------------------------------
61        // 3) En basit kullanım: varsayılan üretici
62        // ---------------------------------------------------------------------
63        System.out.println("--- 3) En kısa kullanım: getDefault() ---");
64        java.util.random.RandomGenerator varsayilan =
65                java.util.random.RandomGenerator.getDefault();
66        System.out.println("  Varsayılan üretici bir zar atışı: " + (varsayilan.nextInt(6) + 1));
67        System.out.println();
68
69        // ---------------------------------------------------------------------
70        // 4) Stream API ile rastgele sayı üretimi
71        // ---------------------------------------------------------------------
72        System.out.println("--- 4) Stream ile 5 adet rastgele sayı ---");
73        String sayilar = varsayilan.ints(5, 1, 101) // 5 adet, [1,100]
74                .mapToObj(Integer::toString)
75                .collect(Collectors.joining(", "));
76        System.out.println("  " + sayilar);
77        System.out.println();
78
79        // ---------------------------------------------------------------------
80        // 5) Kullanılabilir tüm algoritmaları listele
81        // ---------------------------------------------------------------------
82        System.out.println("--- 5) Bu JDK'da mevcut algoritmalar ---");
83        RandomGeneratorFactory.all()
84                .map(RandomGeneratorFactory::name)
85                .sorted()
86                .forEach(ad -> System.out.println("  - " + ad));
87        System.out.println();
88
89        // ---------------------------------------------------------------------
90        // GERÇEK HAYAT NOTU:
91        //  - Güvenlik gerektiren durumlar (token, şifre, anahtar) için DAİMA
92        //    java.security.SecureRandom kullanın; bu algoritmalar genel amaçlıdır.
93        //  - Paralel/çok çekirdekli simülasyonlarda "splittable" (örn. L64X128)
94        //    veya "jumpable" üreticiler tercih edilir (alt-akışlar arası bağımsızlık).
95        //  - Tekrarlanabilir testler için sabit tohum (seed) verin.
96        // ---------------------------------------------------------------------
97        System.out.println("Not: Güvenlik için SecureRandom; simülasyon için splittable üreticiler.");
98    }
99}
Çıktı yerel JDK 21 ile yakalandı — tarayıcıda JVM çalışmaz.

SealedClassesKalici

çalıştırılabilir
SealedClassesKalici.java
1// =============================================================================
2//  SealedClassesKalici.java
3//  JAVA 17 (LTS) - Sealed Classes (Mühürlü Sınıflar) ARTIK KALICI (FINAL)
4// =============================================================================
5//
6//  NEDİR?
7//  Sealed (mühürlü) sınıf/arayüz, KENDİSİNDEN HANGİ SINIFLARIN türeyebileceğini
8//  AÇIKÇA kısıtlar. "permits" listesinde olmayan hiçbir sınıf bu tipi extends
9//  veya implements edemez. Java 15-16'da preview, JAVA 17 ile KALICI oldu.
10//
11//  NEDEN GELDİ?
12//  Java'da bir sınıf ya tamamen "final" (kimse türetemez) ya da tamamen "açık"
13//  (herkes türetebilir) olabiliyordu. Arada bir seçenek yoktu. Bazen şunu
14//  istiyoruz: "Bu tipten SADECE şu 3 sınıf türeyebilsin, başkası türetemesin."
15//  Sealed sınıflar tam olarak bunu sağlar -> KONTROLLÜ, KAPALI bir tip hiyerarşisi.
16//
17//  NE İŞE YARAR / GÜCÜ NEREDE?
18//  Mühürlü hiyerarşi SONLU ve BİLİNEN bir alt-tip kümesi tanımlar. Bu sayede:
19//    - Domain modelini (etki alanı modelini) net biçimde ifade ederiz.
20//    - Pattern matching (switch) ile EKSİKSİZLİK (exhaustiveness) kontrolü
21//      yapılabilir: derleyici tüm olası alt tiplerin ele alındığını DOĞRULAR.
22//    - Records + Sealed + Pattern Matching = "Algebraic Data Types" (bkz.
23//      CebirselVeriTipleri.java)
24//
25//  ANAHTAR KELİMELER:
26//    sealed     -> mühürlü; alt tipleri permits listesiyle sınırlar
27//    permits    -> hangi sınıfların türeyebileceğini listeler
28//    final      -> alt tip artık kimseye kapalı (yaprak/leaf)
29//    non-sealed -> alt tip mührü AÇAR; ondan herkes türeyebilir
30//
31//  Derlemek için: javac SealedClassesKalici.java
32//  Çalıştırmak  : java SealedClassesKalici
33// =============================================================================
34
35public class SealedClassesKalici {
36
37    public static void main(String[] args) {
38
39        System.out.println("=== JAVA 17 (LTS): SEALED CLASSES (KALICI) ===\n");
40
41        // ---------------------------------------------------------------------
42        // 1) Sadece izin verilen alt tipler oluşturulabilir
43        // ---------------------------------------------------------------------
44        System.out.println("--- 1) Mühürlü hiyerarşinin üyeleri ---");
45        Sekil[] sekiller = {
46                new Daire(5),
47                new Kare(4),
48                new Dikdortgen(3, 6)
49        };
50        for (Sekil s : sekiller) {
51            System.out.printf("  %-22s alan = %.2f%n",
52                    s.getClass().getSimpleName(), s.alan());
53        }
54        System.out.println();
55
56        // ---------------------------------------------------------------------
57        // 2) Exhaustiveness (eksiksizlik): switch tüm alt tipleri kapsamalı
58        //    permits listesi kapalı olduğundan derleyici default'a İHTİYAÇ
59        //    duymadan tüm dalların kapsandığını doğrulayabilir.
60        // ---------------------------------------------------------------------
61        System.out.println("--- 2) Mühürlü tip üzerinde güvenli sınıflandırma ---");
62        for (Sekil s : sekiller) {
63            System.out.println("  " + sinifla(s));
64        }
65        System.out.println();
66
67        // ---------------------------------------------------------------------
68        // 3) non-sealed örneği: mührü açan bir dal
69        // ---------------------------------------------------------------------
70        System.out.println("--- 3) non-sealed dal (genişletilebilir) ---");
71        Odeme krediKarti = new KrediKarti("1234");
72        Odeme ozelOdeme  = new OzelKurumsalOdeme(); // non-sealed'dan türemiş
73        System.out.println("  " + krediKarti.aciklama());
74        System.out.println("  " + ozelOdeme.aciklama());
75    }
76
77    // Klasik if-else ama mühürlü tip sayesinde tüm olasılıkları bildiğimizden emin oluruz
78    static String sinifla(Sekil s) {
79        if (s instanceof Daire d) {
80            return "Daire (yarıçap " + d.yaricap() + ")";
81        } else if (s instanceof Kare k) {
82            return "Kare (kenar " + k.kenar() + ")";
83        } else if (s instanceof Dikdortgen r) {
84            return "Dikdörtgen (" + r.en() + "x" + r.boy() + ")";
85        }
86        // permits listesi kapalı; başka alt tip mümkün değil
87        return "Bilinmeyen";
88    }
89
90    // =========================================================================
91    //  MÜHÜRLÜ HİYERARŞİ: Geometrik şekiller
92    //  - Sekil "sealed interface"; sadece Daire, Kare, Dikdortgen türeyebilir.
93    //  - Alt tipler record olduğundan otomatik olarak "final"dır (geçerli).
94    //  - Mühürlü bir tipin tüm izinli alt tipleri AYNI modülde / aynı pakette
95    //    (tek dosyada aynı paket) tanımlanmalıdır.
96    // =========================================================================
97    sealed interface Sekil permits Daire, Kare, Dikdortgen {
98        double alan();
99    }
100
101    // record'lar örtük final olduğu için permits için geçerli yapraklardır
102    record Daire(double yaricap) implements Sekil {
103        public double alan() { return Math.PI * yaricap * yaricap; }
104    }
105
106    record Kare(double kenar) implements Sekil {
107        public double alan() { return kenar * kenar; }
108    }
109
110    record Dikdortgen(double en, double boy) implements Sekil {
111        public double alan() { return en * boy; }
112    }
113
114    // =========================================================================
115    //  final / non-sealed kullanımının gösterimi
116    //  Mühürlü bir tipin HER alt sınıfı şu üçünden BİRİ olmak ZORUNDADIR:
117    //    - final       : artık kapalı (kimse türetemez)
118    //    - sealed      : kendisi de mühürlü (permits ile devam eder)
119    //    - non-sealed  : mührü tekrar açar (herkes türetebilir)
120    // =========================================================================
121    sealed interface Odeme permits KrediKarti, Havale, KurumsalOdeme {
122        String aciklama();
123    }
124
125    // final yaprak
126    record KrediKarti(String sonDortHane) implements Odeme {
127        public String aciklama() { return "Kredi kartı **** " + sonDortHane; }
128    }
129
130    // final yaprak
131    record Havale(String iban) implements Odeme {
132        public String aciklama() { return "Havale/EFT: " + iban; }
133    }
134
135    // non-sealed: bu dalın altı herkese AÇIK (genişletilebilir uzantı noktası)
136    non-sealed interface KurumsalOdeme extends Odeme {}
137
138    // KurumsalOdeme non-sealed olduğu için serbestçe türetilebilir
139    static final class OzelKurumsalOdeme implements KurumsalOdeme {
140        public String aciklama() { return "Özel kurumsal ödeme yöntemi"; }
141    }
142}
143
144// =============================================================================
145//  KURALLAR ÖZETİ — SEALED CLASSES
146//  1) sealed sınıf/arayüz "permits X, Y, Z" ile izinli alt tipleri belirtir.
147//     (Aynı dosyadaysa permits opsiyoneldir; derleyici çıkarımı yapabilir.)
148//  2) Her izinli alt tip final, sealed VEYA non-sealed olmak ZORUNDADIR.
149//  3) Tüm izinli alt tipler, sealed tip ile aynı modül (veya named module yoksa
150//     aynı paket) içinde olmalıdır.
151//  4) record'lar örtük final'dır; mühürlü hiyerarşilerde mükemmel yapraktır.
152//
153//  AVANTAJLARI:
154//   - Domain modeli kapalı ve nettir (kim türeyebilir bellidir).
155//   - Pattern matching switch'te exhaustiveness (default gerekmez).
156//   - API tasarımında kötüye kullanımı önler.
157//
158//  GERÇEK HAYAT KULLANIMI:
159//   - Durum makineleri (state machine)
160//   - Ödeme yöntemleri, mesaj tipleri, AST düğümleri, JSON node tipleri
161//   - Sonuç tipleri: Result = Basari | Hata  (bkz. CebirselVeriTipleri.java)
162// =============================================================================
Çıktı yerel JDK 21 ile yakalandı — tarayıcıda JVM çalışmaz.