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
| Özellik | Değer |
|---|---|
| Sürüm | Java SE 17 / JDK 17 |
| Çıkış Tarihi | 14 Eylül 2021 |
| LTS mi? | EVET — Long-Term Support (Uzun Süreli Destek) |
| Destek Takvimi | Oracle 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 LTS | Java 11 (2018), Java 8 (2014) |
| Sonraki LTS | Java 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ü:
- Uzun destek penceresi: Her 6 ayda bir sürüm yükseltmek zorunda kalmazsınız.
- Ü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.
- Güvenlik: Uzun süre CVE yamaları gelir.
- 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?
| Özellik | Durum | Dosya |
|---|---|---|
| Sealed Classes | KALICI (JEP 409) | SealedClassesKalici.java |
Pattern Matching for switch | Preview (JEP 406) | PatternMatchingSwitch.java |
| Records + Sealed + Pattern (ADT) | Birleşim | CebirselVeriTipleri.java |
| Enhanced Pseudo-Random Generators | KALICI (JEP 356) | RandomGenerator.java |
| Yeni macOS Rendering Pipeline | Kalıcı (JEP 382) | — |
| macOS/AArch64 Portu | Kalıcı (JEP 391) | — |
| Applet API'nin kaldırılmaya hazırlanması | Deprecation (JEP 398) | — |
| Security Manager deprecation | Deprecation (JEP 411) | — |
| Strong Encapsulation (varsayılan) | Kalıcı (JEP 403) | — |
| Foreign Function & Memory API | Incubator (JEP 412) | — |
| Vector API | Incubator (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 tipleripermitsile sınırlarpermits— 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,sealedveyanon-sealedolmak ZORUNDADIR.record'lar örtükfinalolduğ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-previewgerektirir (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)
- Geçersiz durumlar temsil edilemez hale gelir → tip güvenliği.
- Exhaustiveness: Yeni bir varyant eklediğinizde, onu işlemeyen HER
switchderleme hatası verir. "Bir yeri güncellemeyi unuttum" hatası imkânsız olur. - 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):
SecurityManagerkaldı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-openskullanı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
- Strong encapsulation: İç API'lere dayanan eski kütüphaneler kırılabilir → bağımlılıkları güncelleyin, gerekirse
--add-opens. - 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. - Security Manager kullanan kod → alternatif izolasyona geçin.
- Applet kullanan kod → modernleştirin.
- Derleme bayrakları:
--release 17ile derleyin; tüm bağımlılıkların Java 17 uyumlu sürümlerine yükseltin.
Önerilen Geçiş Adımları
- Önce Java 11'e geçin (ara durak), sonra Java 17.
- Tüm bağımlılıkları en güncel sürümlere çıkarın.
jdepsile iç API kullanımını analiz edin.- Test ortamında preview/deprecation uyarılarını giderin.
- Üretim öncesi performans ve GC profilini doğrulayın.
Bu Klasördeki Dosyalar ve Derleme
| Dosya | Preview gerekir mi? |
|---|---|
SealedClassesKalici.java | Hayır |
RandomGenerator.java | Hayır |
PatternMatchingSwitch.java | Evet |
CebirselVeriTipleri.java | Evet |
# 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ılabilir1// =============================================================================
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// =============================================================================PatternMatchingSwitch
çalıştırılabilir1// =============================================================================
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}RandomGenerator
çalıştırılabilir1// =============================================================================
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}SealedClassesKalici
çalıştırılabilir1// =============================================================================
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// =============================================================================