Java 10 (Mart 2018) — Detayli Surum Analizi
> Bu klasor, Java 10'un getirdigi yenilikleri Turkce, derinlemesine ve calisan kod ornekleriyle anlatir.
Java 10 (Mart 2018) — Detayli Surum Analizi
Bu klasor, Java 10'un getirdigi yenilikleri Turkce, derinlemesine ve calisan kod ornekleriyle anlatir.
Surum Bilgisi
| Ozellik | Deger |
|---|---|
| Surum | Java SE 10 (JDK 10) |
| Cikis Tarihi | 20 Mart 2018 |
| Kod Adi | 18.3 (yeni surum numaralandirmasi denemesi) |
| LTS mi? | HAYIR — LTS (Long-Term Support) DEGILDIR |
| Destek Durumu | Sona erdi (sadece Eylul 2018'e kadar resmi guncelleme aldi) |
| Onceki LTS | Java 8 |
| Sonraki LTS | Java 11 (Eylul 2018) |
Yeni 6 Aylik Surum Dongusunun ILK Meyvesi
Java 10, Oracle'in yeni 6 aylik (yari yillik) surum modelinin ilk uygulamasidir.
- Java 9'a kadar surumler arasinda yillar gecerdi (Java 7 → Java 8 arasi ~3 yil, Java 8 → Java 9 arasi ~3.5 yil).
- Java 9 ile birlikte Oracle, her 6 ayda bir yeni bir Java surumu cikarmaya karar verdi (Mart ve Eylul).
- Bu modelde her surum LTS DEGILDIR. Sadece belirli surumler (Java 11, 17, 21, ...) uzun donem destek alir.
- Java 10 "feature release" (ozellik surumu) olarak ciktigi icin, sadece bir sonraki surum (Java 11) cikana kadar (yaklasik 6 ay) guncelleme aldi.
Sonuc: Java 10'u bugun uretimde (production) kullanmak onerilmez. Java 10 ile gelen ozellikler zaten Java 11+ icinde mevcuttur. Java 10'un onemi, getirdigi var ve immutable koleksiyon API'lerinin tum sonraki surumlere tasinmis olmasidir.
Genel Bakis — Java 10 Ne Getirdi?
| JEP | Ozellik | Bu klasordeki dosya |
|---|---|---|
| JEP 286 | Local Variable Type Inference (var) | VarTipCikarimi.java |
| API | Collectors.toUnmodifiable*, List/Set/Map.copyOf | ImmutableCollections.java |
| JEP 307 | Parallel Full GC for G1 | (bu README'de aciklandi) |
| JEP 310 | Application Class-Data Sharing (AppCDS) | (bu README'de aciklandi) |
| JEP 304 | Garbage-Collector Interface | (bu README'de aciklandi) |
| JEP 312 | Thread-Local Handshakes | (kisaca aciklandi) |
| JEP 314 | Additional Unicode Language-Tag Extensions | (kisaca aciklandi) |
| JEP 317 | Experimental JIT Compiler (Graal, deneysel) | (kisaca aciklandi) |
| JEP 296 | JDK kaynak kodu tek depoda birlestirildi | (gelistirici ic yapisi) |
1) var — Yerel Degisken Tip Cikarimi (JEP 286)
Ilgili dosya:
VarTipCikarimi.java
NEDIR?
Yerel degiskenlerin tipini, derleyicinin sag taraftaki ifadeden otomatik cikarmasini saglayan ozelliktir. var bir anahtar kelime degil, "ayrilmis tip adi"dir (bu sayede eski kodlarda var adli degiskenler bozulmaz).
NEDEN GELDI? (Hangi problem?)
Java cok "verbose" (gereksiz uzun) bulunuyordu. Ozellikle uzun generic tiplerde tip adini iki kez yazmak zorunluydu ve bu okunabilirligi dusuruyordu:
Map<String, List<Map<Integer, String>>> veri = new HashMap<String, List<Map<Integer, String>>>();
NE ISE YARAR?
- Kalip kodu (boilerplate) azaltir.
- Uzun generic tiplerde okunabilirligi artirir.
- Degiskenin adina ve anlamina odaklanmayi saglar.
NEREDE KOLAYLIK SAGLAR?
- Karmasik generic tipler
- Stream / Collectors zincirleri
for-eachve klasikfordonguleritry-with-resources
ESKI vs YENI
// ESKI (Java 9 ve oncesi) ArrayList<String> liste = new ArrayList<String>(); Map<String, List<Integer>> harita = new HashMap<String, List<Integer>>(); // YENI (Java 10+) var liste = new ArrayList<String>(); var harita = new HashMap<String, List<Integer>>();
NEREDE KULLANILAMAZ? (Cok Onemli)
var SADECE baslatici (initializer) ile yerel degiskende kullanilir. Su durumlarda KULLANILAMAZ:
- Baslatmasiz:
var x;❌ - Null ile:
var y = null;❌ - Lambda atamasi:
var f = () -> ...;❌ (hedef tip yok) - Metot referansi:
var g = System.out::println;❌ - Dizi kisayolu:
var d = {1,2,3};❌ (amavar d = new int[]{1,2,3};✅) - Birden cok degisken:
var a = 1, b = 2;❌ - Sinif alani (field) ❌
- Metot parametresi ❌
- Metot donus tipi ❌
catchparametresi ❌- Lambda parametresi ❌ (Java 10'da YOK; Java 11/JEP 323 ile geldi)
GERCEK HAYAT ORNEGI
Bir enterprise serviste, repository katmanindan gelen karmasik generic donus tiplerini yazarken:
// ESKI Map<String, List<SiparisDetay>> gruplu = siparisServisi.gruplaMusteriye(); // YENI var gruplu = siparisServisi.gruplaMusteriye();
Metot adi (gruplaMusteriye) anlamli oldugundan tip belirsizlesmez; kod daha temiz olur.
OKUNABILIRLIK RISKI (Best Practice)
var yanlis kullanilirsa kodu okunamaz hale getirebilir:
var x = getir(); // getir() ne donduruyor? Okuyan bilemez -> KOTU
Altin kural: Tip sag taraftan apacik belliyse (new X(), literal, anlamli metot adi) var kullan; degilse acik tip yaz. Ayrica sayisal tuzaklara dikkat: var oran = 5; aslinda int'tir, 5.0 yazmazsan ondalik beklerken tam sayi bolmesi yasarsin.
2) Degistirilemez (Immutable) Koleksiyon Gelistirmeleri
Ilgili dosya:
ImmutableCollections.java
NEDIR?
Java 10 iki yetenek ekledi:
Collectors.toUnmodifiableList/Set/Map— Stream sonucunu dogrudan degistirilemez koleksiyon olarak toplar.List.copyOf / Set.copyOf / Map.copyOf— Var olan bir koleksiyondan degistirilemez bir kopya olusturur.
NEDEN GELDI? (Hangi problem?)
Java 9 List.of(...) getirdi ama bu sifirdan, eleman eleman olusturur. Elimizde zaten bir koleksiyon varsa (orn. metoda parametre olarak geldi) ve degistirilemez kopyasini istiyorsak, eski Collections.unmodifiableList(new ArrayList<>(...)) kalibini kullanmak zorundaydik.
List.of (Java 9) vs List.copyOf (Java 10) FARKI
List.of(a, b, c)→ elemanlari tek tek verirsin, sifirdan olusturur.List.copyOf(coll)→ var olan koleksiyondan bagimsiz, degistirilemez bir kopya alir. Orijinal sonradan degisse bile kopya etkilenmez (gercek defensive copy).
Her ikisi de add/remove/set cagrilirsa UnsupportedOperationException firlatir.
ESKI vs YENI
// ESKI (Java 8/9): once kopya, sonra sar List<String> sonuc = Collections.unmodifiableList(new ArrayList<>(girdi)); // YENI (Java 10): tek satir var sonuc = List.copyOf(girdi);
// ESKI: Stream -> toList -> unmodifiable List<String> r = Collections.unmodifiableList( stream.collect(Collectors.toList())); // YENI: dogrudan var r = stream.collect(Collectors.toUnmodifiableList());
GERCEK HAYAT ORNEGI (Defensive Copy)
Bir Siparis sinifi disaridan urun listesi alir. Listeyi dogrudan saklarsak, disaridaki kod sonradan onu degistirip ic durumumuzu bozabilir. List.copyOf ile degistirilemez kopya saklayarak nesneyi koruruz:
final class Siparis { private final List<String> urunler; Siparis(List<String> urunler) { this.urunler = List.copyOf(urunler); // savunmaci kopya } }
3) JVM / Performans Gelistirmeleri (Kurumsal Sistemler Acisindan)
JEP 307 — G1 icin Paralel Full GC (Parallel Full GC for G1)
NEDIR: G1 (Garbage-First) cop toplayicisinin full GC (tam cop toplama) asamasi, Java 10'a kadar tek is parcacigi (single-threaded) ile calisiyordu.
PROBLEM: G1 normalde dusuk duraklama (low-pause) icin tasarlanmistir, ama bellek baskisi yuksek olup full GC tetiklendiginde tek cekirdek kullandigi icin uzun "stop-the-world" duraklamalari olusuyordu.
COZUM: Full GC artik coklu is parcacigi (parallel, mark-sweep-compact) ile calisir; mevcut tum CPU cekirdeklerini kullanir.
KURUMSAL FAYDA: Buyuk heap'li (orn. 32 GB+) sunucu uygulamalarinda full GC duraklamasi belirgin sekilde kisalir. Bu, dusuk gecikme (latency) bekleyen finans/e-ticaret sistemlerinde tepki sureleri ve SLA acisindan kritiktir. Java 9'da G1 varsayilan GC olmustu; Java 10 onun en zayif noktasini iyilestirdi.
JEP 310 — Application Class-Data Sharing (AppCDS)
NEDIR: CDS (Class-Data Sharing) onceden sadece JDK cekirdek (bootstrap) siniflarini paylasilan bir arsivde tutabiliyordu. AppCDS bunu uygulama siniflarina da genisletti.
NASIL CALISIR: Uygulama siniflari bir kez "class-data archive" dosyasina yazilir; sonraki JVM baslangiclarinda bu arsiv bellek esleme (memory-mapping) ile dogrudan yuklenir ve birden cok JVM ornegi arasinda paylasilir.
KURUMSAL FAYDA:
- Daha hizli baslangic (startup) suresi — siniflar tekrar tekrar parse/dogrulama yapilmadan yuklenir.
- Daha dusuk bellek ayak izi — ayni makinede calisan birden cok JVM ornegi (orn. mikroservis konteynerleri) ortak class metadata'sini paylasir.
- Konteyner/Kubernetes ortamlarinda yogun olcekli (cok ornekli) dagitimlarda toplam RAM tasarrufu saglar; hizli olceklenme (scale-up) onemli oldugunda baslangic gecikmesini azaltir.
JEP 304 — Garbage-Collector Interface (GC Arayuzu)
NEDIR: JVM ic kaynak kodunda cop toplayicilar icin temiz, izole edilmis bir arayuz (interface) tanimlandi.
PROBLEM: Onceden GC kodu JVM'in her yerine dagilmis durumdaydi; yeni bir GC eklemek veya birini cikarmak cok zordu.
FAYDA (cogunlukla gelistirici/JVM bakimi): GC'ler modulerlesti. Bu altyapi sayesinde sonraki surumlerde ZGC (Java 11) ve Shenandoah gibi yeni, dusuk gecikmeli toplayicilarin eklenmesi kolaylasti. Kurumsal acidan dolayli fayda: gelecekte GC secenekleri daha zengin ve bakimi daha kolay hale geldi.
Kisaca Diger JEP'ler
- JEP 312 (Thread-Local Handshakes): Tum is parcaciklarini durdurmadan, tek tek thread'lerle "el sikisma" yapabilme. Bu da global stop-the-world duraklama ihtiyacini azaltir (GC ve diagnostik islemler icin temel altyapi).
- JEP 317 (Graal — Deneysel JIT): Java ile yazilmis Graal derleyicisi, Linux/x64'te deneysel JIT olarak kullanilabilir hale geldi.
- JEP 314 (Unicode dil etiketleri): Ek Unicode BCP 47 dil-etiketi uzantilari (takvim, sayi sistemi vb.) desteklendi.
- JEP 316 (Alternatif bellek aygitlari): Heap'in alternatif bellek aygitlarina (orn. NV-DIMM) yerlestirilebilmesi.
Java 9'dan Java 10'a GECISTE NE DEGISTI?
| Konu | Java 9 | Java 10 |
|---|---|---|
| Yerel degisken tipi | Tipi acikca yazmak zorunlu | var ile cikarim |
| Stream → immutable | Collections.unmodifiableList(...collect(toList())) | Collectors.toUnmodifiableList() |
| Var olan koleksiyondan immutable kopya | Manuel unmodifiable + new ArrayList | List/Set/Map.copyOf(...) |
| G1 Full GC | Tek is parcacikli (yavas duraklama) | Paralel (coklu cekirdek) |
| Class-Data Sharing | Sadece JDK siniflari | Uygulama siniflari da (AppCDS) |
| Surum modeli | Yeni 6 aylik modelin baslangici | Modelin ilk ozellik surumu |
Genel olarak: Java 9'dan 10'a gecis kucuk ama anlamli bir adimdir. Java 9'un getirdigi devrim niteligindeki modul sistemi (JPMS) gibi buyuk degisiklikler yoktu; Java 10 daha cok rahatlatma (var), API tamamlama (copyOf) ve JVM performans iyilestirmesi odakliydi. Gecis genellikle sorunsuzdur cunku geriye donuk uyumluluk korunmustur (var ayrilmis tip adi oldugu icin eski kodlari bozmaz).
Avantaj / Dezavantaj / Risk
Avantajlar
varile daha temiz kod: Ozellikle uzun generic tiplerde okunabilirlik ve yazim hizi artar.- Tamamlanan immutable API:
copyOfvetoUnmodifiable*ile savunmaci programlama (defensive copy) cok kolaylasti. - G1 paralel full GC: Buyuk heap'li sunucularda duraklama sureleri kisaldi.
- AppCDS: Cok ornekli (mikroservis/konteyner) ortamlarda hizli baslangic ve dusuk bellek.
Dezavantajlar
- LTS degil: Uretim icin uygun degil; destek kisa surede sona erdi.
varher yerde calismaz: Field, parametre, donus tipi, lambda parametresi gibi yerlerde kullanilamaz; kurallar akilda tutulmali.- Kucuk olcekli surum: Java 9 ile gelen modul sistemi gibi cigir acan bir yenilik yok.
Riskler
varokunabilirlik riski (en onemli risk): Yanlis kullanilirsa tip belirsizlesir.var x = servis.getir();→ okuyan kisix'in tipini bilemez.- Sayisal tuzak:
var oran = 5;→int! Beklenmeyen tam sayi bolmesine yol acar. - Cozum:
var'i yalnizca sag taraf tipi apacik gosterdiginde kullan; anlamli degisken adlari sec; aksi halde acik tip yaz.
- 6 aylik surum modeli riski: Her surum LTS olmadigi icin, surekli en yeni Java'yi takip eden ekipler sik guncelleme baskisiyla karsilasir. Kurumsal projeler genelde sadece LTS surumlerde (8, 11, 17, 21) kalmayi tercih eder; Java 10 gibi ara surumler atlanir. Bu model, "her surumu uretime alma" yerine "LTS'leri takip et, ara surumleri deneme/gelistirme icin kullan" stratejisini zorunlu kildi.
- Yanlis surum secimi maliyeti: Java 10'u uretimde secen bir ekip, 6 ay sonra zorunlu olarak Java 11'e gecmek (ve test/dogrulama maliyetine katlanmak) durumunda kalirdi.
Bu Klasordeki Dosyalar
README.md— bu dosya (surum analizi ve tum ozelliklerin aciklamasi)VarTipCikarimi.java—var/ yerel degisken tip cikarimi, derinlemesine, kullanilamayan durumlar dahilImmutableCollections.java—Collectors.toUnmodifiable*,List/Set/Map.copyOf, defensive copy senaryosu
Derleme ve Calistirma (JDK 10+ gerektirir)
javac VarTipCikarimi.java && java VarTipCikarimi javac ImmutableCollections.java && java ImmutableCollections
Not: Bu dosyalar
varve Java 10 API'lerini kullandigi icin JDK 10 veya uzeri ile derlenmelidir. Daha eski bir JDK ile derlenmezler.
▶ Kod Örnekleri(2)
ImmutableCollections
çalıştırılabilir1import java.util.ArrayList;
2import java.util.Arrays;
3import java.util.Collections;
4import java.util.LinkedHashMap;
5import java.util.List;
6import java.util.Map;
7import java.util.Set;
8import java.util.stream.Collectors;
9import java.util.stream.Stream;
10
11/**
12 * ============================================================================
13 * Java 10 - DEGISTIRILEMEZ (IMMUTABLE) KOLEKSIYON GELISTIRMELERI
14 * ============================================================================
15 *
16 * Java 10 iki onemli yetenek ekledi:
17 *
18 * 1) Collectors.toUnmodifiableList / toUnmodifiableSet / toUnmodifiableMap
19 * -> Stream sonucunu DOGRUDAN degistirilemez bir koleksiyon olarak toplar.
20 *
21 * 2) List.copyOf / Set.copyOf / Map.copyOf
22 * -> VAR OLAN bir koleksiyondan degistirilemez bir KOPYA olusturur.
23 *
24 * --------------------------------------------------------------------------
25 * NEDEN GELDI? (Hangi problem?)
26 * --------------------------------------------------------------------------
27 * Java 9 "List.of(...)" gibi factory metotlar getirdi. Ama bunlar SIFIRDAN
28 * eleman sayarak immutable koleksiyon olusturur. Elimizde ZATEN bir
29 * koleksiyon varsa (orn. bir metoda parametre olarak geldi) ve bunun
30 * degistirilemez bir kopyasini istiyorsak Java 9'da kolay bir yol yoktu;
31 * eski "Collections.unmodifiableList(new ArrayList<>(...))" kalibini
32 * kullanmak zorundaydik.
33 *
34 * --------------------------------------------------------------------------
35 * List.of (Java 9) ile List.copyOf (Java 10) FARKI
36 * --------------------------------------------------------------------------
37 * - List.of(a, b, c) : elemanlari TEK TEK verirsin, sifirdan olusturur.
38 * - List.copyOf(coll) : VAR OLAN bir koleksiyonu alir, ondan degistirilemez
39 * bir KOPYA cikarir. Orijinal degisse bile kopya
40 * etkilenmez (gercek defensive copy).
41 *
42 * Her ikisi de SONUC olarak degistirilemez koleksiyon verir; add/remove/set
43 * cagirirsan UnsupportedOperationException firlatir.
44 * ============================================================================
45 */
46public class ImmutableCollections {
47
48 public static void main(String[] args) {
49
50 System.out.println("=== 1) Collectors.toUnmodifiableList/Set/Map ===");
51 unmodifiableCollectors();
52
53 System.out.println("\n=== 2) List.copyOf / Set.copyOf / Map.copyOf ===");
54 copyOfOrnegi();
55
56 System.out.println("\n=== 3) List.of (Java 9) vs List.copyOf (Java 10) ===");
57 ofVsCopyOf();
58
59 System.out.println("\n=== 4) ESKI YONTEM vs YENI YONTEM ===");
60 eskiVsYeni();
61
62 System.out.println("\n=== 5) GERCEK HAYAT: DEFENSIVE COPY senaryosu ===");
63 defensiveCopySenaryo();
64
65 System.out.println("\n=== 6) Degistirilemezligin KANITI ===");
66 degistirilemezlikKaniti();
67 }
68
69 /* ------------------------------------------------------------------ */
70 /* 1) Collectors.toUnmodifiable* */
71 /* ------------------------------------------------------------------ */
72 static void unmodifiableCollectors() {
73
74 // ----- ESKI (Java 9): once toList, sonra unmodifiableList sar -----
75 List<String> eski = Collections.unmodifiableList(
76 Stream.of("elma", "armut", "kiraz")
77 .map(String::toUpperCase)
78 .collect(Collectors.toList()));
79
80 // ----- YENI (Java 10): dogrudan degistirilemez listeye topla -----
81 var yeniListe = Stream.of("elma", "armut", "kiraz")
82 .map(String::toUpperCase)
83 .collect(Collectors.toUnmodifiableList());
84
85 var yeniSet = Stream.of(1, 2, 2, 3, 3, 3)
86 .collect(Collectors.toUnmodifiableSet());
87
88 var yeniMap = Stream.of("bir", "iki", "uc")
89 .collect(Collectors.toUnmodifiableMap(
90 kelime -> kelime, // anahtar
91 String::length)); // deger (uzunluk)
92
93 System.out.println("eski (unmodifiableList) = " + eski);
94 System.out.println("yeniListe = " + yeniListe);
95 System.out.println("yeniSet = " + yeniSet);
96 System.out.println("yeniMap = " + yeniMap);
97 }
98
99 /* ------------------------------------------------------------------ */
100 /* 2) copyOf metotlari */
101 /* ------------------------------------------------------------------ */
102 static void copyOfOrnegi() {
103 // Var olan, DEGISTIRILEBILIR bir koleksiyon:
104 var kaynakListe = new ArrayList<>(List.of("a", "b", "c"));
105
106 // copyOf ile degistirilemez bir KOPYA:
107 var kopyaListe = List.copyOf(kaynakListe);
108
109 var kaynakMap = new LinkedHashMap<String, Integer>();
110 kaynakMap.put("x", 1);
111 kaynakMap.put("y", 2);
112 var kopyaMap = Map.copyOf(kaynakMap);
113
114 var kopyaSet = Set.copyOf(List.of(10, 20, 30, 30)); // tekrar elenir
115
116 System.out.println("kopyaListe = " + kopyaListe);
117 System.out.println("kopyaMap = " + kopyaMap);
118 System.out.println("kopyaSet = " + kopyaSet);
119 }
120
121 /* ------------------------------------------------------------------ */
122 /* 3) of vs copyOf farkini KANITLA */
123 /* ------------------------------------------------------------------ */
124 static void ofVsCopyOf() {
125 var orijinal = new ArrayList<>(List.of("ilk", "ikinci"));
126
127 // copyOf: orijinalin O ANKI halinin BAGIMSIZ kopyasi
128 var kopya = List.copyOf(orijinal);
129
130 // Orijinali degistirelim:
131 orijinal.add("sonradan eklendi");
132
133 System.out.println("orijinal (degisti) = " + orijinal);
134 System.out.println("kopya (etkilenmedi)= " + kopya
135 + " <-- copyOf bagimsiz kopya aldigi icin degismedi");
136
137 // List.of ise zaten sifirdan olusturur; elemanlari tek tek veririz:
138 var sifirdan = List.of("p", "q", "r");
139 System.out.println("List.of ile sifirdan = " + sifirdan);
140 }
141
142 /* ------------------------------------------------------------------ */
143 /* 4) ESKI vs YENI - ayni isi yapan iki yaklasim */
144 /* ------------------------------------------------------------------ */
145 static void eskiVsYeni() {
146 var girdi = Arrays.asList("kirmizi", "yesil", "mavi");
147
148 // ----- ESKI YONTEM (Java 8 / 9) -----
149 // 1) Yeni bir ArrayList olustur (kopya), 2) unmodifiable ile sar.
150 List<String> eskiSonuc =
151 Collections.unmodifiableList(new ArrayList<>(girdi));
152
153 // ----- YENI YONTEM (Java 10) - tek satir -----
154 var yeniSonuc = List.copyOf(girdi);
155
156 System.out.println("ESKI: Collections.unmodifiableList(new ArrayList<>(...)) = "
157 + eskiSonuc);
158 System.out.println("YENI: List.copyOf(...) = " + yeniSonuc);
159 System.out.println("Ikisi de icerikce esit mi? " + eskiSonuc.equals(yeniSonuc));
160 }
161
162 /* ------------------------------------------------------------------ */
163 /* 5) GERCEK HAYAT: DEFENSIVE COPY */
164 /* ------------------------------------------------------------------ */
165 /*
166 * Senaryo: Bir "Siparis" sinifi disaridan bir urun listesi aliyor.
167 * Eger listeyi DOGRUDAN saklarsak, disaridaki kod sonradan listeyi
168 * degistirip nesnemizin ic durumunu bozabilir. Bunu engellemek icin
169 * List.copyOf ile DEGISTIRILEMEZ bir KOPYA sakliyoruz (defensive copy).
170 */
171 static void defensiveCopySenaryo() {
172 var disaridanGelenler = new ArrayList<>(List.of("Klavye", "Mouse"));
173
174 var siparis = new Siparis("SIP-001", disaridanGelenler);
175
176 // Disaridaki kod listeyi degistirmeye calisir:
177 disaridanGelenler.add("Korsanlik denemesi!");
178
179 System.out.println("Disaridaki liste = " + disaridanGelenler);
180 System.out.println("Siparis urunleri (KORUNDU) = " + siparis.getUrunler());
181 }
182
183 /** Defensive copy ornegi icin saglam (immutable) Siparis sinifi. */
184 static final class Siparis {
185 private final String no;
186 private final List<String> urunler; // degistirilemez kopya
187
188 Siparis(String no, List<String> urunler) {
189 this.no = no;
190 // KRITIK: gelen referansi DOGRUDAN saklamak yerine kopyala.
191 this.urunler = List.copyOf(urunler);
192 }
193
194 String getNo() { return no; }
195
196 // Geri donerken zaten degistirilemez liste donuyoruz; ek koruma gerekmez.
197 List<String> getUrunler() { return urunler; }
198 }
199
200 /* ------------------------------------------------------------------ */
201 /* 6) Degistirilemezligin KANITI */
202 /* ------------------------------------------------------------------ */
203 static void degistirilemezlikKaniti() {
204 var liste = List.copyOf(List.of("a", "b"));
205 try {
206 liste.add("c"); // UnsupportedOperationException firlatir
207 } catch (UnsupportedOperationException e) {
208 System.out.println("Beklenen hata yakalandi: add() yapilamaz "
209 + "(UnsupportedOperationException). Liste degistirilemez.");
210 }
211 }
212}VarTipCikarimi
çalıştırılabilir1import java.util.ArrayList;
2import java.util.HashMap;
3import java.util.List;
4import java.util.Map;
5import java.util.stream.Collectors;
6import java.util.stream.Stream;
7
8/**
9 * ============================================================================
10 * Java 10 - YEREL DEGISKEN TIP CIKARIMI (Local Variable Type Inference)
11 * JEP 286: "var" anahtar kelimesi
12 * ============================================================================
13 *
14 * NEDIR?
15 * ------
16 * Java 10 ile gelen "var", YEREL degiskenlerin tipini derleyicinin
17 * (compiler) sag taraftaki ifadeden (initializer) otomatik cikarmasini
18 * saglar. Boylece tipi iki kez yazmak zorunda kalmayiz.
19 *
20 * ONEMLI: "var" bir anahtar kelime (keyword) DEGILDIR, "ayrilmis tip adi"
21 * (reserved type name) olarak tanimlanmistir. Bu sayede daha once
22 * degisken/metot adi olarak "var" kullanan eski kodlar bozulmaz.
23 *
24 * NEDEN GELDI? (Hangi problem?)
25 * -----------------------------
26 * Java cok "verbose" (gereksiz uzun) bir dil olmakla elestiriliyordu.
27 * Ozellikle generic tipler cok uzadiginda tip adini SOL ve SAG tarafta
28 * iki kez yazmak hem yoruyor hem de okunabilirligi dusuruyordu:
29 *
30 * Map<String, List<Map<Integer, String>>> veri =
31 * new HashMap<String, List<Map<Integer, String>>>();
32 *
33 * Bu tekrar "boilerplate" (kalip kod) olarak goruluyordu. var bunu cozer.
34 *
35 * NE ISE YARAR?
36 * -------------
37 * - Kod tekrarini azaltir (tip adini bir kez yazariz).
38 * - Uzun generic tiplerde okunabilirligi ARTIRIR.
39 * - Degisken ADINA ve degerin ANLAMINA odaklanmamizi saglar.
40 *
41 * NEREDE KOLAYLIK SAGLAR?
42 * -----------------------
43 * - Karmasik generic tipler
44 * - Stream/Collectors zincirleri
45 * - for-each ve klasik for donguleri
46 * - try-with-resources
47 *
48 * DIKKAT: var, tip GUVENLIGINI (type safety) BOZMAZ. Bu JavaScript'teki
49 * "var" gibi DINAMIK tip DEGILDIR. Tip derleme aninda sabittir; sadece
50 * yazmiyoruz. Calisma aninda (runtime) hicbir ek maliyet yoktur.
51 * ============================================================================
52 */
53public class VarTipCikarimi {
54
55 public static void main(String[] args) {
56
57 System.out.println("=== 1) TEMEL KULLANIM (ESKI vs YENI) ===");
58 temelKullanim();
59
60 System.out.println("\n=== 2) UZUN GENERIC TIPLER ===");
61 uzunGenericTipler();
62
63 System.out.println("\n=== 3) FOR-EACH ve KLASIK FOR DONGUSU ===");
64 donguler();
65
66 System.out.println("\n=== 4) TRY-WITH-RESOURCES ===");
67 tryWithResources();
68
69 System.out.println("\n=== 5) STREAM / COLLECTORS ZINCIRI ===");
70 streamOrnegi();
71
72 System.out.println("\n=== 6) NEREDE KULLANILAMAZ (yorum icinde) ===");
73 nereDeKullanilamaz();
74
75 System.out.println("\n=== 7) OKUNABILIRLIK: IYI vs KOTU KULLANIM ===");
76 okunabilirlik();
77 }
78
79 /* ------------------------------------------------------------------ */
80 /* 1) TEMEL KULLANIM */
81 /* ------------------------------------------------------------------ */
82 static void temelKullanim() {
83
84 // ----- ESKI YONTEM (Java 9 ve oncesi) -----
85 String mesajEski = "Merhaba";
86 int sayiEski = 42;
87 double oranEski = 3.14;
88 ArrayList<String> listeEski = new ArrayList<String>();
89
90 // ----- YENI YONTEM (Java 10+) -----
91 // Derleyici sag taraftan tipi cikarir:
92 var mesaj = "Merhaba"; // String olarak cikarilir
93 var sayi = 42; // int olarak cikarilir
94 var oran = 3.14; // double olarak cikarilir
95 var liste = new ArrayList<String>(); // ArrayList<String> cikarilir
96
97 // DIKKAT: var ile tanimlanan tip DEGISMEZ. Asagidaki satir
98 // DERLENMEZ cunku 'sayi' artik int'tir, String atanamaz:
99 // sayi = "yazi"; // HATA: incompatible types
100
101 System.out.println("mesaj=" + mesaj + ", sayi=" + sayi
102 + ", oran=" + oran + ", liste boyutu=" + liste.size());
103 System.out.println("Eski yontem cikti: " + mesajEski + " " + sayiEski
104 + " " + oranEski + " " + listeEski.size());
105 }
106
107 /* ------------------------------------------------------------------ */
108 /* 2) UZUN GENERIC TIPLER - var'in en parladigi yer */
109 /* ------------------------------------------------------------------ */
110 static void uzunGenericTipler() {
111
112 // ----- ESKI: tip adini iki kez yazmak zorundayiz -----
113 Map<String, List<Integer>> haritaEski =
114 new HashMap<String, List<Integer>>();
115
116 // ----- YENI: tek satir, tek tip -----
117 var harita = new HashMap<String, List<Integer>>();
118 harita.put("asal", List.of(2, 3, 5, 7));
119 harita.put("cift", List.of(2, 4, 6, 8));
120
121 System.out.println("harita = " + harita);
122 System.out.println("haritaEski boyutu = " + haritaEski.size());
123 }
124
125 /* ------------------------------------------------------------------ */
126 /* 3) DONGULER (for-each ve klasik for) */
127 /* ------------------------------------------------------------------ */
128 static void donguler() {
129
130 var sehirler = List.of("Ankara", "Istanbul", "Izmir", "Bursa");
131
132 // for-each icinde var (element tipi String olarak cikarilir)
133 System.out.println("for-each:");
134 for (var sehir : sehirler) {
135 System.out.println(" - " + sehir);
136 }
137
138 // Klasik for dongusunde var (i, int olarak cikarilir)
139 System.out.println("klasik for:");
140 for (var i = 0; i < sehirler.size(); i++) {
141 System.out.println(" [" + i + "] " + sehirler.get(i));
142 }
143 }
144
145 /* ------------------------------------------------------------------ */
146 /* 4) TRY-WITH-RESOURCES */
147 /* ------------------------------------------------------------------ */
148 static void tryWithResources() {
149 // var, try-with-resources icinde de kullanilabilir.
150 // Burada ornek olarak kendi AutoCloseable kaynagimizi kullaniyoruz.
151 try (var kaynak = new BasitKaynak("VeritabaniBaglantisi")) {
152 kaynak.kullan();
153 }
154 // try blogu bitince kaynak otomatik kapatilir (close cagrilir).
155 }
156
157 /** try-with-resources demosu icin basit kapatilabilir kaynak. */
158 static class BasitKaynak implements AutoCloseable {
159 private final String ad;
160 BasitKaynak(String ad) {
161 this.ad = ad;
162 System.out.println(" ACILDI: " + ad);
163 }
164 void kullan() {
165 System.out.println(" KULLANILIYOR: " + ad);
166 }
167 @Override
168 public void close() {
169 System.out.println(" KAPATILDI: " + ad);
170 }
171 }
172
173 /* ------------------------------------------------------------------ */
174 /* 5) STREAM / COLLECTORS ZINCIRI */
175 /* ------------------------------------------------------------------ */
176 static void streamOrnegi() {
177 // Stream ara/son sonuclarini var ile tutmak okunabilirligi artirir.
178 var sayilar = Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
179
180 // var ile sonuc (List<Integer>)
181 var ciftKareler = sayilar
182 .filter(n -> n % 2 == 0) // ciftleri sec
183 .map(n -> n * n) // karesini al
184 .collect(Collectors.toList());
185
186 System.out.println("Cift sayilarin kareleri = " + ciftKareler);
187 }
188
189 /* ------------------------------------------------------------------ */
190 /* 6) NEREDE KULLANILAMAZ? (Hepsi yorum icinde - dosya derlensin diye) */
191 /* ------------------------------------------------------------------ */
192 static void nereDeKullanilamaz() {
193 System.out.println("Asagidaki yasakli kullanimlar yorum icinde aciklandi.");
194
195 // -------------------------------------------------------------
196 // KURAL: var SADECE bir baslatici (initializer) ile YEREL
197 // degiskende kullanilabilir. Asagidakilerin HICBIRI DERLENMEZ:
198 // -------------------------------------------------------------
199
200 // (a) BASLATMASIZ degisken - tip cikarilamaz:
201 // var x; // HATA: cannot infer type
202 // x = 10;
203
204 // (b) NULL ile baslatma - null'in tipi belirsizdir:
205 // var y = null; // HATA: variable initializer is 'null'
206
207 // (c) LAMBDA atamasi - hedef tip (target type) gerekir:
208 // var f = () -> System.out.println("hi"); // HATA
209 // (Lambda hangi functional interface? Derleyici bilemez.)
210
211 // (d) METOT REFERANSI - yine hedef tip gerekir:
212 // var g = System.out::println; // HATA
213
214 // (e) DIZI baslaticisi (kosesi parantez kisayolu):
215 // var dizi = { 1, 2, 3 }; // HATA: array initializer needs type
216 // (Ancak var dizi = new int[]{1,2,3}; GECERLIDIR.)
217
218 // (f) Ayni satirda BIRDEN COK degisken:
219 // var a = 1, b = 2; // HATA: 'var' is not allowed in a compound declaration
220
221 // -------------------------------------------------------------
222 // var ASLA su yerlerde KULLANILAMAZ (yerel degisken degiller):
223 // -------------------------------------------------------------
224 // (g) SINIF ALANI (field):
225 // private var alan = 5; // HATA
226 // (h) METOT PARAMETRESI:
227 // void m(var p) { } // HATA
228 // (i) METOT DONUS TIPI:
229 // var hesapla() { return 1; } // HATA
230 // (j) CATCH parametresi:
231 // catch (var e) { } // HATA
232 // (k) Java 10'da LAMBDA PARAMETRESI:
233 // (var s) -> s.length() // Java 10'da YOK
234 // NOT: Lambda parametresinde var, Java 11 (JEP 323) ile geldi.
235
236 // GECERLI olan ozel durum: var ile new int[]{...}
237 var gecerliDizi = new int[]{1, 2, 3};
238 System.out.println(" Gecerli dizi uzunlugu = " + gecerliDizi.length);
239 }
240
241 /* ------------------------------------------------------------------ */
242 /* 7) OKUNABILIRLIK - IYI vs KOTU KULLANIM (BEST PRACTICE) */
243 /* ------------------------------------------------------------------ */
244 static void okunabilirlik() {
245
246 // ----- IYI KULLANIM: tip sag taraftan ACIKCA bellidir -----
247 var musteri = new Musteri("Ayse", 30); // tip net: Musteri
248 var siparisler = new ArrayList<String>(); // tip net
249 var toplamTutar = hesaplaTutar(); // metot adi anlamli
250
251 System.out.println("IYI: " + musteri + ", siparis=" + siparisler.size()
252 + ", tutar=" + toplamTutar);
253
254 // ----- KOTU KULLANIM ORNEKLERI (aciklama) -----
255 //
256 // (1) Tip belirsiz kalir, sag taraf yeterince acik degil:
257 // var x = getir(); // getir() ne donduruyor? Okuyan bilemez!
258 // Bu durumda ACIK tip yazmak daha iyidir: BigDecimal x = getir();
259 //
260 // (2) Sayisal literal tuzaklari:
261 // var oran = 5; // bu int! ama belki double istiyorduk
262 // Eger double istiyorsak ya var oran = 5.0; ya da double oran = 5;
263 //
264 // (3) "Programci anlasin diye" anlamli degisken adi SECMEZ ve var
265 // kullanirsak okuyan kisi tipi tahmin etmek zorunda kalir.
266 //
267 // ALTIN KURAL:
268 // - var, tip APACIK ise (new X(), literal, anlamli metot adi) KULLAN.
269 // - var, tip belirsizlestiriyorsa (kisa/anlamsiz metot adi) KULLANMA.
270 // - Degisken adini var ile birlikte DAHA ANLAMLI sec.
271
272 // Sayisal tuzak demosu:
273 var oranYanlis = 5; // int -> tam sayi bolmesi riski
274 var oranDogru = 5.0; // double -> ondalik
275 System.out.println("oranYanlis/2 = " + (oranYanlis / 2)
276 + " (int bolme!) oranDogru/2 = " + (oranDogru / 2));
277 }
278
279 static java.math.BigDecimal hesaplaTutar() {
280 return new java.math.BigDecimal("199.90");
281 }
282
283 /** Okunabilirlik ornegi icin basit veri sinifi. */
284 static class Musteri {
285 final String ad;
286 final int yas;
287 Musteri(String ad, int yas) { this.ad = ad; this.yas = yas; }
288 @Override public String toString() { return ad + "(" + yas + ")"; }
289 }
290}