Eğitim Portalı/Sürüm Analizi/Java 10 (Mart 2018) — Detayli Surum Analizi
Sürüm Analizi05-java-versiyon-analizi/03-Java-10

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

OzellikDeger
SurumJava SE 10 (JDK 10)
Cikis Tarihi20 Mart 2018
Kod Adi18.3 (yeni surum numaralandirmasi denemesi)
LTS mi?HAYIR — LTS (Long-Term Support) DEGILDIR
Destek DurumuSona erdi (sadece Eylul 2018'e kadar resmi guncelleme aldi)
Onceki LTSJava 8
Sonraki LTSJava 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?

JEPOzellikBu klasordeki dosya
JEP 286Local Variable Type Inference (var)VarTipCikarimi.java
APICollectors.toUnmodifiable*, List/Set/Map.copyOfImmutableCollections.java
JEP 307Parallel Full GC for G1(bu README'de aciklandi)
JEP 310Application Class-Data Sharing (AppCDS)(bu README'de aciklandi)
JEP 304Garbage-Collector Interface(bu README'de aciklandi)
JEP 312Thread-Local Handshakes(kisaca aciklandi)
JEP 314Additional Unicode Language-Tag Extensions(kisaca aciklandi)
JEP 317Experimental JIT Compiler (Graal, deneysel)(kisaca aciklandi)
JEP 296JDK 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-each ve klasik for donguleri
  • try-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}; ❌ (ama var d = new int[]{1,2,3}; ✅)
  • Birden cok degisken: var a = 1, b = 2;
  • Sinif alani (field) ❌
  • Metot parametresi ❌
  • Metot donus tipi ❌
  • catch parametresi ❌
  • 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:

  1. Collectors.toUnmodifiableList/Set/Map — Stream sonucunu dogrudan degistirilemez koleksiyon olarak toplar.
  2. 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?

KonuJava 9Java 10
Yerel degisken tipiTipi acikca yazmak zorunluvar ile cikarim
Stream → immutableCollections.unmodifiableList(...collect(toList()))Collectors.toUnmodifiableList()
Var olan koleksiyondan immutable kopyaManuel unmodifiable + new ArrayListList/Set/Map.copyOf(...)
G1 Full GCTek is parcacikli (yavas duraklama)Paralel (coklu cekirdek)
Class-Data SharingSadece JDK siniflariUygulama siniflari da (AppCDS)
Surum modeliYeni 6 aylik modelin baslangiciModelin 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

  • var ile daha temiz kod: Ozellikle uzun generic tiplerde okunabilirlik ve yazim hizi artar.
  • Tamamlanan immutable API: copyOf ve toUnmodifiable* 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.
  • var her 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

  • var okunabilirlik riski (en onemli risk): Yanlis kullanilirsa tip belirsizlesir.
    • var x = servis.getir(); → okuyan kisi x'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.javavar / yerel degisken tip cikarimi, derinlemesine, kullanilamayan durumlar dahil
  • ImmutableCollections.javaCollectors.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 var ve 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ılabilir
ImmutableCollections.java
1import 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}
Çıktı yerel JDK 21 ile yakalandı — tarayıcıda JVM çalışmaz.

VarTipCikarimi

çalıştırılabilir
VarTipCikarimi.java
1import 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}
Çıktı yerel JDK 21 ile yakalandı — tarayıcıda JVM çalışmaz.