Eğitim Portalı/Sürüm Analizi/Java 25 (Eylül 2025) — EN GÜNCEL LTS SÜRÜMÜ
Sürüm Analizi05-java-versiyon-analizi/18-Java-25

Java 25 (Eylül 2025) — EN GÜNCEL LTS SÜRÜMÜ

> Bu klasör, Java-Versiyon-Analizi serisinin en detaylı bölümüdür. > Çünkü Java 25, şu an piyasadaki en güncel LTS (Long-Term Support) sürümüdür > ve 2026 itibarıyla kurumsal projelerin birincil hedef sürümüdür.

Java 25 (Eylül 2025) — EN GÜNCEL LTS SÜRÜMÜ

Bu klasör, Java-Versiyon-Analizi serisinin en detaylı bölümüdür. Çünkü Java 25, şu an piyasadaki en güncel LTS (Long-Term Support) sürümüdür ve 2026 itibarıyla kurumsal projelerin birincil hedef sürümüdür.


1. Sürüm Bilgisi

ÖzellikDeğer
SürümJava 25 (JDK 25)
Çıkış tarihiEylül 2025
Destek tipiLTS (Long-Term Support)
Bir önceki LTSJava 21 (Eylül 2023)
Ondan önceki LTSJava 17 (Eylül 2021)
Sürüm kadansıHer 6 ayda bir feature release, her 2 yılda bir LTS

Not (dürüstlük): JEP numaralarını ve hangi özelliğin kalıcı/preview olduğunu mümkün olduğunca doğru verdim. Emin olmadığım kesin imzalar/sayısal detaylarda genel kaldım ve "resmi JEP'e bakın" notu düştüm. Uydurma yapmadım.


2. LTS NEDEN BU KADAR ÖNEMLİ? (GÜÇLÜ VURGU)

LTS Nedir?

LTS = Long-Term Support (Uzun Süreli Destek). Oracle ve OpenJDK ekosistemi, sürümleri her 6 ayda bir yayınlar. Ancak bu sürümlerin çoğu yalnızca 6 ay güncelleme alır (feature release / non-LTS). LTS sürümleri ise yıllarca (genellikle 8+ yıl, dağıtıcıya göre değişir) güvenlik yamaları ve hata düzeltmeleri alır.

Kurumsallar Neden LTS Bekler?

Bir non-LTS sürüm (örn. Java 22, 23, 24) çıktığında, kurumsal şirketler genelde onları production'a almaz. Bunun nedenleri:

  1. Uzun destek penceresi: Bir bankanın çekirdek sistemini her 6 ayda bir yeni JDK'ya taşıması imkânsızdır. LTS, "kur ve yıllarca güvenle kullan" demektir.
  2. Güvenlik güncellemeleri: LTS dışı bir sürüm 6 ay sonra güncelleme almaz; yeni keşfedilen güvenlik açıkları (CVE) yamalanmaz. Bu, kurumsal için kabul edilemez.
  3. Kararlılık (stability): LTS sürümlerinde özellikler oturmuş, preview'lar kalıcılaşmış, ekosistem (kütüphaneler, framework'ler, araçlar) uyum sağlamıştır.
  4. Uyumluluk & sertifikasyon: Spring, Jakarta EE, uygulama sunucuları (Tomcat, WildFly), build araçları (Maven, Gradle) ve bulut sağlayıcıları desteklerini önce LTS sürümlere verir.
  5. Maliyet & risk yönetimi: Sık yükseltme = sürekli test/regresyon maliyeti. LTS, yükseltme döngüsünü 2–3 yıla yayarak riski ve maliyeti düşürür.

Java 25 = Yeni Kurumsal Hedef

  • Java 8 uzun yıllar fiili standarttı (hâlâ çok yaygın).
  • Java 11 ilk modern LTS olarak benimsendi.
  • Java 17 "modern Java"ya geçişin omurgası oldu (records, sealed, pattern matching).
  • Java 21 sanal thread'ler (virtual threads) ile devrim yaptı.
  • Java 25 ise bu birikimi olgunlaştırarak kalıcı hale getirdi: Scoped Values, Flexible Constructor Bodies, Compact Source Files, Module Import Declarations gibi özellikler artık preview değil, standart.

Sonuç: 2026'da yeni bir kurumsal proje başlatıyorsanız ya da mevcut bir sistemi yükseltiyorsanız hedef sürüm Java 25 olmalıdır. Java 17 veya 21'de kalan ekipler için 25, "bir sonraki güvenli durak"tır.


3. Genel Bakış — Java 25 Neler Getirdi?

Java 25 hem kalıcılaşan hem de hâlâ preview olan özellikler içerir. Aşağıdaki tablo durumu dürüstçe özetler:

ÖzellikJEPDurum (Java 25)Örnek Dosya
Compact Source Files & Instance Main512KALICICompactSourceMainMethods.java
Scoped Values506KALICIScopedValuesKalici.java
Flexible Constructor Bodies513KALICIFlexibleConstructorBodies.java
Module Import Declarations511KALICI(README)
Stable Values502PREVIEWStableValuesPreview.java
Structured Concurrency505PREVIEW (5.)StructuredConcurrencyGuncel.java
PEM Encodings of Crypto Objects470PREVIEW(README)
Primitive Types in Patterns/instanceof/switch507PREVIEW (devam)(README)
Compact Object Headers519Ürün özelliği (JVM)(README)
Generational Shenandoahİyileştirme (JVM)(README)

4. Özellik Detayları

Her özellik için: NEDİR / NEDEN GELDİ / NE İŞE YARAR / NEREDE KOLAYLIK SAĞLAR / ESKİ vs YENİ / GERÇEK HAYAT.


4.1. Compact Source Files & Instance Main Methods — KALICI (JEP 512)

Dosya: CompactSourceMainMethods.java

  • NEDİR: Bir .java dosyasını sınıf bildirimi (public class ...) olmadan, doğrudan void main() ile yazabilme. main artık static, public ve String[] args zorunlu değil. Ayrıca IO.println(...) / IO.readln(...) otomatik kullanılabilir.
  • NEDEN GELDİ: Yeni başlayanların "Merhaba Dünya" yazmak için public, static, void, String[] args ve class kavramlarını aynı anda öğrenme bariyerini kaldırmak. Java'yı öğrenmeye giriş kolaylaştırılır.
  • NE İŞE YARAR: Kavramların kademeli öğretilmesini sağlar; küçük script/araçlar için boilerplate'i azaltır.
  • NEREDE KOLAYLIK: Eğitim, prototipleme, tek dosyalık yardımcı programlar.
  • ESKİ vs YENİ:
    // ESKİ (Java 1.0–24)
    public class Merhaba {
        public static void main(String[] args) {
            System.out.println("Merhaba Dünya");
        }
    }
    // YENİ (Java 25 - KALICI)
    void main() {
        IO.println("Merhaba Dünya");
    }
  • GERÇEK HAYAT: Bir öğrenci ilk günden tek satır kodla girdi/çıktı yapabilir; bir DevOps mühendisi java arac.java ile hızlı bir bakım scripti çalıştırabilir.
  • Tarih (dürüst): Java 21 → 24 arasında 4 farklı preview adından geçti (Unnamed Classes → Implicitly Declared → Simple Source → Compact Source). Java 25'te nihayet kalıcı oldu, --enable-preview gerekmez.

4.2. Scoped Values — KALICI (JEP 506)

Dosya: ScopedValuesKalici.java

  • NEDİR: ScopedValue<T>, bir thread ve onun alt görevleri boyunca değişmez bir bağlam değeri taşımanın modern yolu. ThreadLocal'a alternatiftir.
  • NEDEN GELDİ: ThreadLocal değiştirilebilir (mutable), remove() unutulursa thread havuzlarında bellek sızıntısına yol açar ve milyonlarca sanal thread ile pahalıdır. Scoped Values bu sorunları çözer.
  • NE İŞE YARAR: İstek (request) bağlamı, kullanıcı kimliği, korelasyon ID'si, dil/lokal bilgisi gibi verileri parametre zinciri olmadan alt katmanlara taşır.
  • NEREDE KOLAYLIK: Web sunucuları, mikroservis çağrı zincirleri, loglama bağlamı (MDC benzeri), güvenlik bağlamı.
  • ESKİ vs YENİ:
    // ESKİ: ThreadLocal (mutable, remove() unutulursa sızıntı)
    static final ThreadLocal<Kullanici> TL = new ThreadLocal<>();
    TL.set(kullanici); try { ... } finally { TL.remove(); }
    
    // YENİ: ScopedValue (immutable, otomatik temizlik, sanal thread dostu)
    ScopedValue.where(AKTIF_KULLANICI, kullanici).run(() -> { ... });
  • GERÇEK HAYAT: Bir HTTP isteği geldiğinde kullanıcı + istek ID'si bağlama konur; servis ve veri erişim katmanları bu değerleri parametre taşımadan okur. Blok bittiğinde değer otomatik geçersizleşir.

4.3. Flexible Constructor Bodies — KALICI (JEP 513)

Dosya: FlexibleConstructorBodies.java

  • NEDİR: super(...) veya this(...) çağrısından önce ifade çalıştırabilme (alan doğrulama, ön hesaplama). Kısıt: bu çağrıdan önce this'in alanlarına/metotlarına erişilemez.
  • NEDEN GELDİ: Eskiden super(...) ilk satır olmak zorundaydı; doğrulama yapmak için statik yardımcı metot hilesi gerekiyordu.
  • NE İŞE YARAR: Argüman doğrulama, dönüşüm, ön hesaplama yapılmasını doğal ve okunabilir kılar.
  • NEREDE KOLAYLIK: Değer nesneleri (value objects), domain modelleri, immutable sınıflar.
  • ESKİ vs YENİ:
    // ESKİ: static metot hilesi
    public Calisan(String ad, int maas) {
        super(dogrula(maas)); // hile
        this.ad = ad;
    }
    private static int dogrula(int m) { if (m<0) throw ...; return m; }
    
    // YENİ (Java 25 - KALICI)
    public Calisan(String ad, int maas) {
        if (maas < 0) throw new IllegalArgumentException("...");
        super(maas);      // doğrudan
        this.ad = ad;
    }
  • GERÇEK HAYAT: Cember(double yaricap) → alanı super'a göndermeden önce hesaplar; Dikdortgen(double kenar)this(kenar, kenar) çağrısından önce doğrulama yapar.

4.4. Module Import Declarations — KALICI (JEP 511)

(README)

  • NEDİR: import module M; ile bir modülün dışa açtığı tüm paketleri tek satırda import edebilme.
  • NEDEN GELDİ: Çok sayıda tekil import satırını azaltmak; özellikle eğitim ve hızlı kod yazımında kolaylık.
  • ESKİ vs YENİ:
    // ESKİ
    import java.util.List;
    import java.util.Map;
    import java.util.stream.Collectors;
    // YENİ
    import module java.base;   // java.base modülünün açtığı tüm paketler
  • NEREDE KOLAYLIK: Compact source dosyaları + module import birlikte, Java'ya girişi ciddi şekilde sadeleştirir. Büyük projelerde tekil import'lar hâlâ tercih edilebilir (açıklık için).

4.5. Stable Values — PREVIEW (JEP 502)

Dosya: StableValuesPreview.java--enable-preview gerekir.

  • NEDİR: StableValue<T>, en fazla bir kez atanan, sonra değişmez olan bir tutucu. Lazy (tembel) başlatma için tasarlanmış.
  • NEDEN GELDİ: final alanlar hemen atanmak zorundadır (lazy olamaz). Lazy yapmak için tarihsel olarak hatalı double-checked locking kullanılırdı. StableValue, "final'ın performansı + lazy'nin esnekliği" sunar; JIT atandıktan sonra değeri sabit gibi optimize edebilir (constant folding).
  • ESKİ vs YENİ:
    // ESKİ: double-checked locking (hataya açık, uzun)
    private volatile Agir n;
    Agir get() { if (n==null) synchronized(this){ if(n==null) n=new Agir(); } return n; }
    
    // YENİ (PREVIEW): tek satır, güvenli
    private final StableValue<Agir> n = StableValue.of();
    Agir get() { return n.orElseSet(() -> new Agir()); }
  • GERÇEK HAYAT: Pahalı bir veritabanı bağlantı dizesini/önbelleğini yalnızca ilk ihtiyaçta bir kez hesaplayıp cache'lemek.
  • DÜRÜSTLÜK NOTU: PREVIEW olduğu için API isimleri (of, orElseSet) sürümler arası değişebilir; resmi JEP 502'ye bakın.

4.6. Structured Concurrency — HÂLÂ PREVIEW (JEP 505)

Dosya: StructuredConcurrencyGuncel.java--enable-preview gerekir.

  • DÜRÜSTLÜK NOTU: Bu özellik Java 25'te kalıcı DEĞİL, hâlâ preview (5. tur). API son turlarda değişti (eski ShutdownOnFailure yerine StructuredTaskScope.open(...) + Joiner).
  • NEDİR: Aynı mantıksal işi yapan birden çok eş zamanlı alt görevi tek bir birim gibi ele alma. Bir görev başarısız olursa diğerleri otomatik iptal edilir.
  • NEDEN GELDİ: ExecutorService + Future ile iptal yayılımı elle yapılır, thread sızıntısı riski vardır, hata yönetimi dağınıktır.
  • NE İŞE YARAR: Birden çok servisten paralel veri çekme, hata yayılımı, iptal, zaman aşımı yönetimini yapısal ve okunabilir kılar.
  • ESKİ vs YENİ:
    // ESKİ (yapısız): f1 patlarsa f2 iptal edilmez
    Future<A> f1 = ex.submit(...); Future<B> f2 = ex.submit(...);
    // YENİ (PREVIEW): biri patlarsa diğeri otomatik iptal
    try (var scope = StructuredTaskScope.open(...)) {
        var t1 = scope.fork(() -> servisA());
        var t2 = scope.fork(() -> servisB());
        scope.join();
        return birlestir(t1.get(), t2.get());
    }
  • GERÇEK HAYAT: Bir kullanıcı profilini oluşturmak için "temel bilgi" ve "sipariş özeti" servislerini paralel çağırıp birleştirme; biri 503 dönerse diğeri iptal edilir, hata yukarı yayılır.

4.7. PEM Encodings of Cryptographic Objects — PREVIEW (JEP 470)

(README)

  • NEDİR: Kriptografik nesnelerin (anahtarlar, sertifikalar) PEM (Base64, -----BEGIN ...----- bloklu) metin formatında kodlanması/çözülmesi için standart API.
  • NEDEN GELDİ: Eskiden PEM ile çalışmak için elle Base64 + sınır satırı işleme ya da üçüncü parti kütüphane (örn. BouncyCastle) gerekiyordu.
  • DÜRÜSTLÜK NOTU: PREVIEW. TLS sertifikaları, SSH anahtarları gibi yaygın formatlarla çalışan güvenlik kodları için kolaylık hedefler.

4.8. Primitive Types in Patterns, instanceof, switch — PREVIEW (devam)

(README)

  • NEDİR: instanceof ve switch pattern matching'in ilkel tipleri (int, long, double...) de desteklemesi.
  • NEDEN GELDİ: Pattern matching'i yalnızca referans tiplerle sınırlı bırakmamak; sayısal aralık/dönüşüm kontrollerini daha güvenli yazmak.
  • DÜRÜSTLÜK NOTU: Hâlâ PREVIEW. Örnek:
    if (x instanceof int i) { ... }   // PREVIEW
    switch (deger) { case int i -> ...; case double d -> ...; }

4.9. JVM / Performans İyileştirmeleri (genel)

(README)

  • Compact Object Headers (JEP 519): Nesne başlıklarını küçülterek heap kullanımını azaltır; bellek tasarrufu ve daha iyi cache davranışı sağlar. (Java 24'te deneysel/JEP 450 idi, 25'te ürün özelliği olarak olgunlaştı.)
  • Generational GC iyileştirmeleri: Shenandoah'ın generational varyantı gibi çöp toplayıcı iyileştirmeleri, düşük gecikmeli (low-latency) iş yükleri için.
  • Sanal thread olgunlaşması: Java 21'de kalıcılaşan virtual threads, Scoped Values + Structured Concurrency ile birlikte daha güçlü bir eşzamanlılık modeli oluşturur.

Dürüstlük: Performans JEP'lerinin kesin sayısal kazanımları iş yüküne bağlıdır; genel kaldım, somut yüzde vaadi vermedim.


5. Önceki Preview Özellikler Nasıl Olgunlaştı? (Olgunlaşma Tablosu)

Modern Java'nın felsefesi: özellikler preview → kalıcı yolculuğundan geçer. Java 25, bu olgunlaşmanın çoğunu tamamladığı için bir LTS "toplama noktası"dır.

ÖzellikÖnceJava 25'teki durum
RecordsJava 14 previewKalıcı (16'dan beri) — yaygın
Sealed ClassesJava 15 previewKalıcı (17)
Pattern Matching (switch)Java 17 previewKalıcı (21)
Sanal Thread'lerJava 19 previewKalıcı (21)
Sequenced CollectionsJava 21Kalıcı (21)
Stream GatherersJava 22 previewKalıcı (24)
Foreign Function & Memory (FFM)uzun previewKalıcı (22)
Scoped ValuesJava 20 incubatorKalıcı (25, JEP 506)
Flexible Constructor BodiesJava 22 previewKalıcı (25, JEP 513)
Compact Source & Instance MainJava 21 previewKalıcı (25, JEP 512)
Module Import DeclarationsJava 23 previewKalıcı (25, JEP 511)
Structured ConcurrencyJava 19 incubatorHÂLÂ preview (25, JEP 505)
Stable ValuesJava 25preview (JEP 502)
String TemplatesJava 21–22 previewGERİ ÇEKİLDİ — DİKKAT (aşağıda)

String Templates — DÜRÜST UYARI

  • String Templates (STR."...") Java 21 ve 22'de preview olarak geldi.
  • Java 23'te tasarım sorunları nedeniyle GERİ ÇEKİLDİ (kaldırıldı).
  • Java 25'te String Templates YOKTUR. Bu önemli bir derstir: her preview özellik kalıcılaşmaz; bazıları tamamen iptal olabilir.
  • Bugün string birleştirme için hâlâ +, String.format(...), StringBuilder veya MessageFormat kullanılır.

Çıkarım: Preview özelliklere production'da bel bağlamayın. LTS'in değeri tam da burada: 25'te kalıcı olanlar, "geri çekilme riski" geçmiş özelliklerdir.


6. Geçiş Rehberi: Java 17 / 21 → Java 25

17 → 25 (büyük sıçrama)

17 ile 25 arasında çok şey değişti. Dikkat edilecekler:

  1. Sanal thread'ler (21): I/O ağırlıklı sunucularda thread havuzu modelini yeniden değerlendirin.
  2. Deprecate/kaldırılanlar: sun.misc.Unsafe'in bazı bellek metotları, eski güvenlik yöneticisi (Security Manager) gibi unsurlar kullanım dışı bırakıldı. Üçüncü parti kütüphanelerinizin uyumunu kontrol edin.
  3. Kapsüllenmiş JDK içi API'ler: Güçlü kapsülleme (strong encapsulation) nedeniyle --add-opens ile zorlayan kütüphaneler kırılabilir.
  4. Build araçları: Maven/Gradle, derleyici eklentilerini ve hedef sürümü (--release 25) güncelleyin.

21 → 25 (daha yumuşak)

21 zaten modern bir temel olduğu için geçiş görece kolaydır:

  1. Yeni kalıcı özellikleri benimseyin: Scoped Values (ThreadLocal yerine), Flexible Constructor Bodies, Module Import.
  2. Preview kullanıyorsanız: Bazı 21 preview'ları 25'te kalıcılaştı; kodunuzdan --enable-preview bayraklarını kaldırmanız gerekebilir.
  3. String Templates kullandıysanız: 23'te kaldırıldığı için kodunuzu String.format/+'a geri çevirmeniz gerekir.

Genel Geçiş Adımları

  1. Bağımlılıkları (Spring Boot 3.x+, vb.) Java 25 destekleyen sürümlere yükseltin.
  2. --release 25 ile derleyin, derleme uyarılarını giderin.
  3. Test paketini (unit + entegrasyon) çalıştırın; GC log'larını gözlemleyin.
  4. Staging ortamında performans/regresyon testi yapın.
  5. Kademeli (canary) dağıtımla production'a alın.

7. Avantaj / Dezavantaj / Risk

Avantajlar

  • LTS: Yıllarca güvenlik ve hata düzeltmesi → kurumsal güven.
  • Olgunlaşmış özellikler: Scoped Values, Flexible Constructors, Compact Source artık kalıcı; preview riski yok.
  • Performans/bellek: Compact Object Headers, GC iyileştirmeleri.
  • Modern eşzamanlılık: Virtual threads + Scoped Values güçlü kombinasyon.
  • Öğrenme kolaylığı: Compact source + module import + IO.

Dezavantajlar / Riskler

  • Hâlâ preview olanlar: Structured Concurrency ve Stable Values kalıcı değil; production'da bel bağlamak risklidir, API değişebilir.
  • Kaldırılan API'ler: Eski güvenlik yöneticisi, bazı Unsafe metotları → eski kütüphaneler kırılabilir.
  • 17'den büyük sıçrama: Test/regresyon maliyeti; bağımlılık uyumu.
  • String Templates yok: 23'te kaldırıldı; ona bel bağlamış kod taşınamaz.

8. Dosya Referansları (bu klasör)

DosyaKonuDerleme notu
README.mdBu doküman
CompactSourceMainMethods.javaCompact source & instance main (KALICI)javac / java (preview gerekmez)
ScopedValuesKalici.javaScoped Values (KALICI)javac / java (preview gerekmez)
FlexibleConstructorBodies.javaEsnek constructor (KALICI)javac / java (preview gerekmez)
StableValuesPreview.javaStable Values (PREVIEW)javac --release 25 --enable-preview ...
StructuredConcurrencyGuncel.javaStructured Concurrency (PREVIEW)javac --release 25 --enable-preview ...

Hızlı Çalıştırma

# Kalıcı özellikler (preview bayrağı gerekmez)
javac CompactSourceMainMethods.java && java CompactSourceMainMethods
javac ScopedValuesKalici.java       && java ScopedValuesKalici
javac FlexibleConstructorBodies.java && java FlexibleConstructorBodies

# Preview özellikler (--enable-preview ZORUNLU)
javac --release 25 --enable-preview StableValuesPreview.java
java  --enable-preview StableValuesPreview

javac --release 25 --enable-preview StructuredConcurrencyGuncel.java
java  --enable-preview StructuredConcurrencyGuncel

9. Özet — Neden Java 25?

Java 25, modern Java'nın yıllardır biriken yeniliklerini kalıcılaştıran, uzun süre destek alacak ve ekosistemin etrafında toplanacağı en güncel LTS sürümüdür. 2026'da yeni proje başlatan ya da 17/21'den yükselten her ekip için varsayılan hedef budur. Preview özelliklerin (Structured Concurrency, Stable Values) henüz olgunlaşmadığını ve String Templates'in geri çekildiğini unutmadan, kalıcı özellikleri gönül rahatlığıyla kullanabilirsiniz.

Kod Örnekleri(5)

CompactSourceMainMethods

çalıştırılabilir
CompactSourceMainMethods.java
1// ============================================================================
2//  Java 25 - Compact Source Files & Instance Main Methods (JEP 512 - KALICI)
3// ============================================================================
4//  Bu dosya, Java 25 ile birlikte KALICI (final/standard) hale gelen
5//  "Compact Source Files" ve "Instance Main Methods" ozelligini anlatir.
6//
7//  ONEMLI TARIHCE (DURUST OZET):
8//    - Java 21 (JEP 445): "Unnamed Classes and Instance Main Methods" (preview)
9//    - Java 22 (JEP 463): "Implicitly Declared Classes..." (2. preview)
10//    - Java 23 (JEP 477): "Implicitly Declared Classes and Instance Main
11//                          Methods" (3. preview) + otomatik java.io importlari
12//    - Java 24 (JEP 495): "Simple Source Files and Instance Main Methods"
13//                          (4. preview)
14//    - Java 25 (JEP 512): "Compact Source Files and Instance Main Methods"
15//                          -> NIHAYET KALICI! Artik --enable-preview gerekmez.
16//
17//  Bu dosyanin KENDISI klasik bir sinif icinde main barindirir, cunku bir
18//  ".java" dosyasinda hem aciklama yapip hem de "compact" sentaksini ayni
19//  dosyada gostermek istiyoruz. Compact source ornekleri YORUM olarak
20//  asagida sunulmustur; ayrica calistirilabilir bir karsilastirma da var.
21// ============================================================================
22
23public class CompactSourceMainMethods {
24
25    // ------------------------------------------------------------------------
26    //  1) KLASIK (Java 1.0 - 24) YONTEM
27    // ------------------------------------------------------------------------
28    //  Yeni baslayan biri "Merhaba Dunya" yazmak icin sunlari OGRENMEK zorundaydi:
29    //    - "public" niye var?         (erisim belirleyici)
30    //    - "static" niye var?         (nesne olmadan cagrilabilirlik)
31    //    - "void" niye var?           (donus tipi)
32    //    - "String[] args" niye var?  (komut satiri argumanlari)
33    //    - "class" sarmali niye var?  (her seyin bir sinifta olmasi)
34    //  Bu 5 kavram, ilk satir kodu yazmadan once kafa karistirir.
35    //
36    //  Klasik hali:
37    //
38    //      public class Merhaba {
39    //          public static void main(String[] args) {
40    //              System.out.println("Merhaba Dunya");
41    //          }
42    //      }
43
44    public static void main(String[] args) {
45        System.out.println("=== Java 25: Compact Source & Instance Main ===\n");
46
47        klasikYontemAciklama();
48        yeniYontemAciklama();
49        otomatikImportAciklama();
50        ogrenmeEgrisiKarsilastirmasi();
51
52        System.out.println("\n--- Calistirilabilir mini gosterim ---");
53        // Asagidaki instance-stili metodu, klasik dosyada normal bir nesne
54        // uretip cagirarak "instance main" mantigini simule ediyoruz.
55        CompactSourceMainMethods uygulama = new CompactSourceMainMethods();
56        uygulama.calis();
57    }
58
59    // ------------------------------------------------------------------------
60    //  2) YENI (Java 25, JEP 512) YONTEM - COMPACT SOURCE FILE
61    // ------------------------------------------------------------------------
62    static void yeniYontemAciklama() {
63        System.out.println(">> YENI YONTEM (Java 25 - KALICI):");
64        System.out.println("   Bir .java dosyasinin tamami su kadar olabilir:\n");
65        System.out.println("       void main() {");
66        System.out.println("           IO.println(\"Merhaba Dunya\");");
67        System.out.println("       }\n");
68        System.out.println("   Aciklama:");
69        System.out.println("   - 'class' bildirimi YOK -> derleyici gizli (compact) bir");
70        System.out.println("     sinif olusturur. Buna 'compact source file' denir.");
71        System.out.println("   - main artik 'static' OLMAK ZORUNDA DEGIL -> instance main.");
72        System.out.println("   - 'String[] args' parametresi ZORUNLU DEGIL -> argumansiz main.");
73        System.out.println("   - 'public' belirleyicisi ZORUNLU DEGIL.");
74        System.out.println("   - IO.println(...) otomatik kullanilabilir (java.io.IO).\n");
75    }
76
77    static void klasikYontemAciklama() {
78        System.out.println(">> KLASIK YONTEM (Java 1.0 - 24):");
79        System.out.println("       public class Merhaba {");
80        System.out.println("           public static void main(String[] args) {");
81        System.out.println("               System.out.println(\"Merhaba Dunya\");");
82        System.out.println("           }");
83        System.out.println("       }");
84        System.out.println("   -> Yeni baslayan 5 farkli kavrami ayni anda ogrenmek zorunda.\n");
85    }
86
87    // ------------------------------------------------------------------------
88    //  3) OTOMATIK IMPORT EDILEN IO
89    // ------------------------------------------------------------------------
90    static void otomatikImportAciklama() {
91        System.out.println(">> OTOMATIK IO (java.io.IO):");
92        System.out.println("   Compact source dosyalarinda asagidaki gibi kisa metotlar");
93        System.out.println("   otomatik kullanilabilir (ek import gerekmeden):");
94        System.out.println("       IO.println(\"...\");   // ekrana yazar");
95        System.out.println("       IO.print(\"...\");     // satir sonu eklemeden yazar");
96        System.out.println("       String ad = IO.readln(\"Adiniz: \"); // kullanicidan okur");
97        System.out.println("   Bu sayede System.out.println / Scanner ezberi ilk gunden");
98        System.out.println("   gerekmez; ogrenci hizlica girdi-cikti yapabilir.\n");
99    }
100
101    // ------------------------------------------------------------------------
102    //  4) OGRENME EGRISI KARSILASTIRMASI
103    // ------------------------------------------------------------------------
104    static void ogrenmeEgrisiKarsilastirmasi() {
105        System.out.println(">> NEDEN GELDI / NE ISE YARAR:");
106        System.out.println("   - Egitimde 'ilk program' bariyerini dusurur.");
107        System.out.println("   - Kavramlari ASAMALI ogretmeyi mumkun kilar:");
108        System.out.println("       Asama 1: void main() { ... }           (en sade)");
109        System.out.println("       Asama 2: void main(String[] args)      (argumanlar)");
110        System.out.println("       Asama 3: static void main(...)         (statiklik)");
111        System.out.println("       Asama 4: public class ... { ... }      (sinif/erisim)");
112        System.out.println("   - Kurumsal kodda da kucuk script/araclar icin sadelik saglar.");
113        System.out.println("   - DIKKAT: Buyuk projelerde hala klasik sinif yapisi kullanilir;");
114        System.out.println("     bu ozellik onu YOK ETMEZ, alternatif/giris yolu sunar.\n");
115    }
116
117    // ------------------------------------------------------------------------
118    //  Instance main mantigini simule eden ornek (klasik dosyada nesne ile)
119    // ------------------------------------------------------------------------
120    void calis() {
121        // Java 25'te compact source dosyasinda bu metot dogrudan 'void main()'
122        // olarak yazilabilir ve nesneyi JVM kendisi olusturur.
123        System.out.println("Instance metot calisti (compact source'ta 'void main()' olurdu).");
124    }
125}
126
127/*
128 ============================================================================
129  GERCEK COMPACT SOURCE ORNEGI (ayri bir dosyaya kopyalanarak denenebilir)
130 ============================================================================
131  Asagidaki icerigi "Selam.java" adli AYRI bir dosyaya yazip
132  Java 25 ile soyle calistirabilirsiniz:
133
134      java Selam.java        (kaynak dosyasini dogrudan calistirma)
135
136  --- Selam.java icerigi (compact source - Java 25) ---
137
138      void main() {
139          IO.println("Merhaba Dunya - Compact Source!");
140          String ad = IO.readln("Adiniz nedir? ");
141          IO.println("Hos geldin, " + ad + "!");
142      }
143
144  --- BU ORNEK NIYE ONEMLI ---
145  - Toplam 4 satir. 'class', 'public', 'static', 'String[] args',
146    'System.out', 'import' YOK.
147  - Java 25'te KALICI oldugu icin --enable-preview GEREKMEZ.
148
149  NOT (DURUSTLUK): Compact source dosyasinda alanlar ve baska metotlar da
150  tanimlanabilir; bunlar gizli sinifin uyeleri olur. Birden fazla
151  "compact" dosyayi normal sekilde import edip kullanmak ise klasik
152  modulariteyi gerektirir.
153 ============================================================================
154*/
Çıktı yerel JDK 21 ile yakalandı — tarayıcıda JVM çalışmaz.

FlexibleConstructorBodies

ortam gerekir
FlexibleConstructorBodies.java
1// ============================================================================
2//  Java 25 - Flexible Constructor Bodies (JEP 513 - KALICI)
3// ============================================================================
4//  Flexible Constructor Bodies, Java 25 ile birlikte KALICI (standart) oldu.
5//  Artik --enable-preview gerekmez.
6//
7//  TARIHCE (DURUST OZET):
8//    - Java 22 (JEP 447): Statements before super(...) (preview)
9//    - Java 23 (JEP 482): Flexible Constructor Bodies (2. preview)
10//    - Java 24 (JEP 492): Flexible Constructor Bodies (3. preview)
11//    - Java 25 (JEP 513): KALICI (standard)
12//
13//  NEDIR:
14//    Eskiden bir yapilandiricida (constructor) super(...) veya this(...)
15//    cagrisi MUTLAKA ilk satir olmak zorundaydi. Artik bu cagridan ONCE
16//    "prologue" (on bolum) adi verilen ifadeler calistirilabilir:
17//      - alan dogrulama (validation)
18//      - argumanlar uzerinde on hesaplama / donusum
19//      - super'a gonderilecek degeri hazirlama
20//    KISIT: super()/this() cagrisindan ONCE, henuz olusmakta olan nesnenin
21//    alanlarina/metotlarina ERISILEMEZ (this hala tam kurulmadi).
22//
23//  DERLEME / CALISTIRMA (Java 25):
24//    javac FlexibleConstructorBodies.java
25//    java  FlexibleConstructorBodies
26// ============================================================================
27
28public class FlexibleConstructorBodies {
29
30    public static void main(String[] args) {
31        System.out.println("=== Java 25: Flexible Constructor Bodies (KALICI) ===\n");
32
33        eskiVsYeniAciklama();
34
35        System.out.println("\n--- 1) Alan dogrulama (super'dan ONCE) ---");
36        try {
37            new Calisan("Ahmet", -5000); // gecersiz maas -> super'a gitmeden hata
38        } catch (IllegalArgumentException e) {
39            System.out.println("Beklenen hata: " + e.getMessage());
40        }
41        Calisan c = new Calisan("Zeynep", 45000);
42        System.out.println("Olusturuldu: " + c);
43
44        System.out.println("\n--- 2) On hesaplama / donusum (super'dan ONCE) ---");
45        Cember cember = new Cember(2.0);
46        System.out.println("Cember -> " + cember);
47
48        System.out.println("\n--- 3) this(...) oncesi calismayla varsayilan uretme ---");
49        Dikdortgen kare = new Dikdortgen(5.0);   // tek argumanli -> kare
50        Dikdortgen dik  = new Dikdortgen(3.0, 4.0);
51        System.out.println("Kare       -> " + kare);
52        System.out.println("Dikdortgen -> " + dik);
53    }
54
55    static void eskiVsYeniAciklama() {
56        System.out.println(">> ESKI YONTEM (Java 24 ve oncesi):");
57        System.out.println("   super(...) ILK satir olmak zorundaydi. Dogrulama yapmak icin");
58        System.out.println("   genelde STATIK YARDIMCI METOT hilesine basvurulurdu:\n");
59        System.out.println("       public Calisan(String ad, int maas) {");
60        System.out.println("           super(dogrula(maas));   // hile: static metot ile dogrula");
61        System.out.println("           this.ad = ad;");
62        System.out.println("       }");
63        System.out.println("       private static int dogrula(int m) {");
64        System.out.println("           if (m < 0) throw new IllegalArgumentException(...);");
65        System.out.println("           return m;");
66        System.out.println("       }\n");
67        System.out.println(">> YENI YONTEM (Java 25 - KALICI):");
68        System.out.println("       public Calisan(String ad, int maas) {");
69        System.out.println("           if (maas < 0)                       // super'dan ONCE!");
70        System.out.println("               throw new IllegalArgumentException(...);");
71        System.out.println("           super(maas);                        // dogrudan, hile yok");
72        System.out.println("           this.ad = ad;");
73        System.out.println("       }");
74        System.out.println("   -> Daha okunabilir, ekstra static metot YOK, niyet acik.\n");
75    }
76}
77
78// ----------------------------------------------------------------------------
79//  Ust sinif: bir maas alanini tutar.
80// ----------------------------------------------------------------------------
81class Personel {
82    protected final int maas;
83    Personel(int maas) {
84        this.maas = maas;
85    }
86}
87
88// ----------------------------------------------------------------------------
89//  1) ALAN DOGRULAMA: super(...) cagrisindan ONCE dogrulama yapiyoruz.
90//     Yeni Java 25 ile bu tamamen yasal ve okunabilir.
91// ----------------------------------------------------------------------------
92class Calisan extends Personel {
93    private final String ad;
94
95    Calisan(String ad, int maas) {
96        // super(...) cagrisindan ONCE calisan ifadeler (prologue):
97        if (ad == null || ad.isBlank()) {
98            throw new IllegalArgumentException("Ad bos olamaz");
99        }
100        if (maas < 0) {
101            throw new IllegalArgumentException("Maas negatif olamaz: " + maas);
102        }
103        // Dogrulama gectikten sonra ust yapilandiriciyi cagiriyoruz:
104        super(maas);
105        // super()'dan SONRA artik this'e erisebiliriz:
106        this.ad = ad;
107    }
108
109    @Override
110    public String toString() {
111        return "Calisan{ad='" + ad + "', maas=" + maas + "}";
112    }
113}
114
115// ----------------------------------------------------------------------------
116//  2) ON HESAPLAMA: super'a gonderilecek degeri, cagri oncesinde hesapliyoruz.
117// ----------------------------------------------------------------------------
118class Sekil {
119    protected final double alan;
120    Sekil(double alan) {
121        this.alan = alan;
122    }
123}
124
125class Cember extends Sekil {
126    private final double yaricap;
127
128    Cember(double yaricap) {
129        // Yaricaptan alani super'a gondermeden ONCE hesapliyoruz.
130        if (yaricap <= 0) {
131            throw new IllegalArgumentException("Yaricap pozitif olmali");
132        }
133        double hesaplananAlan = Math.PI * yaricap * yaricap;
134        super(hesaplananAlan);
135        this.yaricap = yaricap;
136    }
137
138    @Override
139    public String toString() {
140        return String.format("Cember{yaricap=%.1f, alan=%.4f}", yaricap, alan);
141    }
142}
143
144// ----------------------------------------------------------------------------
145//  3) this(...) ONCESI calisma: argumanlardan varsayilan turetip
146//     baska yapilandiriciya yonlendirme.
147// ----------------------------------------------------------------------------
148class Dikdortgen {
149    final double en;
150    final double boy;
151
152    // Asil yapilandirici
153    Dikdortgen(double en, double boy) {
154        this.en = en;
155        this.boy = boy;
156    }
157
158    // Tek argumanli: kare olusturmak icin. this(...) ONCESI dogrulama yapiyoruz.
159    Dikdortgen(double kenar) {
160        if (kenar <= 0) {
161            throw new IllegalArgumentException("Kenar pozitif olmali");
162        }
163        // this(...) cagrisindan once ifade calistirabiliyoruz (Java 25).
164        this(kenar, kenar);
165    }
166
167    @Override
168    public String toString() {
169        return String.format("Dikdortgen{en=%.1f, boy=%.1f, alan=%.1f}", en, boy, en * boy);
170    }
171}
canlı çalıştırma için ortam gerekir

Bu sürüm-analizi örneği tek dosya olarak yerel JDK 21 ile çalıştırılamadı (bağımsız bir main içermeyebilir ya da daha yeni bir JDK / önizleme özelliği gerektirir). İlgili dil özelliği yukarıdaki anlatım ve kodda gösterilmiştir.

ScopedValuesKalici

ortam gerekir
ScopedValuesKalici.java
1// ============================================================================
2//  Java 25 - Scoped Values (JEP 506 - KALICI)
3// ============================================================================
4//  Scoped Values, Java 25 ile birlikte KALICI (standart) hale geldi.
5//  Artik --enable-preview gerekmez.
6//
7//  TARIHCE (DURUST OZET):
8//    - Java 20 (JEP 429): Scoped Values (incubator)
9//    - Java 21 (JEP 446): preview
10//    - Java 22 (JEP 464): 2. preview
11//    - Java 23 (JEP 481): 3. preview
12//    - Java 24 (JEP 487): 4. preview
13//    - Java 25 (JEP 506): KALICI (standard)
14//
15//  NEDIR:
16//    ScopedValue<T>, bir is parcacigi (thread) ve onun olusturdugu alt
17//    gorevler boyunca DEGISMEZ (immutable) bir baglam degeri tasimanin
18//    modern, guvenli yoludur. ThreadLocal'in yerine gecen, sanal thread
19//    (virtual thread) dostu bir alternatiftir.
20//
21//  DERLEME / CALISTIRMA (Java 25):
22//    javac ScopedValuesKalici.java
23//    java  ScopedValuesKalici
24//    (KALICI oldugu icin --enable-preview GEREKMEZ.)
25// ============================================================================
26
27import java.util.concurrent.Callable;
28
29public class ScopedValuesKalici {
30
31    // ------------------------------------------------------------------------
32    //  ScopedValue tanimi: tum uygulama boyunca paylasilan, ama degeri sadece
33    //  belirli bir "scope" (kapsam) icinde gecerli olan baglam.
34    //  Tipik kullanim: oturum acmis kullanicinin kimligi, istek (request) ID'si,
35    //  dil/lokal bilgisi, yetki seviyesi gibi "baglamsal" veriler.
36    // ------------------------------------------------------------------------
37    private static final ScopedValue<Kullanici> AKTIF_KULLANICI = ScopedValue.newInstance();
38    private static final ScopedValue<String> ISTEK_ID = ScopedValue.newInstance();
39
40    // Basit bir kullanici modeli (record ile)
41    record Kullanici(String kullaniciAdi, String rol) {}
42
43    public static void main(String[] args) {
44        System.out.println("=== Java 25: Scoped Values (KALICI) ===\n");
45
46        threadLocalVsScopedValueAciklama();
47
48        System.out.println("\n--- GERCEK HAYAT SENARYOSU: Web istegi baglami ---");
49        // Bir web sunucusunun gelen istegi isledigini hayal edin.
50        // Her istek icin kullaniciyi ve istek ID'sini baglama koyuyoruz.
51        gelenIstegiIsle(new Kullanici("ayse", "ADMIN"), "REQ-1001");
52        System.out.println();
53        gelenIstegiIsle(new Kullanici("mehmet", "USER"), "REQ-1002");
54
55        System.out.println("\n--- KAPSAM DISI ERISIM (hata yonetimi) ---");
56        try {
57            // Scope disinda deger okumak istisna firlatir.
58            System.out.println(AKTIF_KULLANICI.get());
59        } catch (Exception e) {
60            System.out.println("Beklenen hata: scope disinda deger okunamaz -> "
61                    + e.getClass().getSimpleName());
62        }
63    }
64
65    // ------------------------------------------------------------------------
66    //  THREADLOCAL vs SCOPEDVALUE
67    // ------------------------------------------------------------------------
68    static void threadLocalVsScopedValueAciklama() {
69        System.out.println(">> ESKI YONTEM: ThreadLocal");
70        System.out.println("   ThreadLocal<Kullanici> tl = new ThreadLocal<>();");
71        System.out.println("   tl.set(kullanici);   // DEGISTIRILEBILIR (mutable)");
72        System.out.println("   ... is bitince ...");
73        System.out.println("   tl.remove();          // UNUTULURSA bellek sizintisi!");
74        System.out.println("   Sorunlar:");
75        System.out.println("   - remove() unutulursa thread havuzlarinda sizinti olur.");
76        System.out.println("   - Her yerden set() ile degistirilebilir -> izlenmesi zor.");
77        System.out.println("   - Milyonlarca sanal thread'de hafiza maliyeti yuksek.\n");
78
79        System.out.println(">> YENI YONTEM: ScopedValue");
80        System.out.println("   ScopedValue.where(AKTIF_KULLANICI, kullanici)");
81        System.out.println("              .run(() -> { ... });  // sadece bu blokta gecerli");
82        System.out.println("   Avantajlar:");
83        System.out.println("   - DEGISMEZ: blok icinde deger degistirilemez -> guvenli.");
84        System.out.println("   - OTOMATIK temizlik: blok bitince deger gecersizlesir,");
85        System.out.println("     remove() cagirmaya gerek YOK.");
86        System.out.println("   - Sanal thread dostu: alt gorevlere otomatik miras kalir.");
87        System.out.println("   - Kapsam acikca bellidir (lexical scope).\n");
88    }
89
90    // ------------------------------------------------------------------------
91    //  GERCEK HAYAT: Gelen bir istegi isleme
92    // ------------------------------------------------------------------------
93    static void gelenIstegiIsle(Kullanici kullanici, String istekId) {
94        // ScopedValue.where(...).run(...) ile baglami SADECE bu blok ve
95        // bu bloktan cagrilan tum alt metotlar icin gecerli kiliyoruz.
96        ScopedValue.where(AKTIF_KULLANICI, kullanici)
97                   .where(ISTEK_ID, istekId)
98                   .run(() -> {
99                       System.out.println("[" + istekId + "] Istek alindi.");
100                       // Alt katmanlar baglami parametre tasimadan okuyabilir:
101                       servisKatmaniCagir();
102                   });
103    }
104
105    // Bu metot kullanici parametresi ALMADI ama baglamdan okuyabiliyor.
106    static void servisKatmaniCagir() {
107        String istekId = ISTEK_ID.get();
108        System.out.println("[" + istekId + "] Servis katmani calisiyor...");
109        veriErisimKatmaniCagir();
110    }
111
112    static void veriErisimKatmaniCagir() {
113        // En alt katman bile, parametre zinciri olmadan aktif kullaniciya erisir.
114        Kullanici k = AKTIF_KULLANICI.get();
115        String istekId = ISTEK_ID.get();
116        System.out.println("[" + istekId + "] Veri erisimi: kullanici="
117                + k.kullaniciAdi() + ", rol=" + k.rol());
118
119        // Yetki kontrolu ornegi:
120        if ("ADMIN".equals(k.rol())) {
121            System.out.println("[" + istekId + "] -> ADMIN: tum kayitlara erisim verildi.");
122        } else {
123            System.out.println("[" + istekId + "] -> USER: sadece kendi kayitlarina erisim.");
124        }
125    }
126
127    // ------------------------------------------------------------------------
128    //  Deger DONDUREN bir scope ornegi (call ile) - referans amacli
129    // ------------------------------------------------------------------------
130    @SuppressWarnings("unused")
131    static <T> T baglamdaCalistir(Kullanici k, Callable<T> gorev) throws Exception {
132        // run(Runnable) deger dondurmez; deger dondurmek icin call(Callable) kullanilir.
133        return ScopedValue.where(AKTIF_KULLANICI, k).call(gorev);
134    }
135}
canlı çalıştırma için ortam gerekir

Bu sürüm-analizi örneği tek dosya olarak yerel JDK 21 ile çalıştırılamadı (bağımsız bir main içermeyebilir ya da daha yeni bir JDK / önizleme özelliği gerektirir). İlgili dil özelliği yukarıdaki anlatım ve kodda gösterilmiştir.

StableValuesPreview

ortam gerekir
StableValuesPreview.java
1// ============================================================================
2//  Java 25 - Stable Values (JEP 502 - PREVIEW)
3// ============================================================================
4//  DIKKAT: Stable Values, Java 25'te HALA PREVIEW asamasindadir (JEP 502).
5//  Yani API ileride degisebilir ve calistirmak icin --enable-preview gerekir.
6//
7//  DERLEME / CALISTIRMA (Java 25 - PREVIEW):
8//      javac --release 25 --enable-preview StableValuesPreview.java
9//      java  --enable-preview StableValuesPreview
10//
11//  NEDIR:
12//    StableValue<T>, bir defaya mahsus (en fazla bir kez) atanan, ondan
13//    sonra DEGISMEZ (immutable) hale gelen bir "tutucu"dur. Asil amaci:
14//    LAZY (tembel/gec) baslatma -> deger ilk ihtiyac aninda hesaplanir,
15//    sonra cache'lenir. JIT derleyici, deger atandiktan sonra onu adeta
16//    'final' gibi optimize edebilir (constant folding). Yani:
17//      "final'in performansi + lazy'nin esnekligi"
18//
19//  NEDEN GELDI:
20//    - 'final' alanlar yapilandiricida HEMEN atanmak zorundadir (lazy degil).
21//    - Lazy yapmak icin tarihsel olarak "double-checked locking" gibi hata
22//      yapmaya cok acik desenler kullanilirdi.
23//    - StableValue, bu deseni guvenli, kisa ve performansli sekilde sunar.
24// ============================================================================
25
26import java.util.function.Supplier;
27
28public class StableValuesPreview {
29
30    public static void main(String[] args) {
31        System.out.println("=== Java 25: Stable Values (PREVIEW - JEP 502) ===\n");
32        System.out.println("(Calistirma: java --enable-preview StableValuesPreview)\n");
33
34        eskiDoubleCheckedLockingAciklama();
35
36        System.out.println("\n--- StableValue ile lazy init ornegi ---");
37        Konfigurasyon konfig = new Konfigurasyon();
38
39        System.out.println("Nesne olusturuldu; agir kaynak HENUZ hesaplanmadi.");
40        System.out.println("(Tembellik: ilk get() cagrilana kadar hesaplama yok.)\n");
41
42        // Ilk erisim -> hesaplama burada bir kez yapilir:
43        System.out.println("1. erisim: " + konfig.getBaglantiDizesi());
44        // Ikinci erisim -> cache'ten gelir, tekrar hesaplanmaz:
45        System.out.println("2. erisim: " + konfig.getBaglantiDizesi());
46        System.out.println("3. erisim: " + konfig.getBaglantiDizesi());
47
48        System.out.println("\nDikkat: 'AGIR HESAPLAMA' yazisi sadece BIR KEZ gorunmeli.");
49    }
50
51    static void eskiDoubleCheckedLockingAciklama() {
52        System.out.println(">> ESKI YONTEM: Double-Checked Locking (hata yapmaya acik)");
53        System.out.println("       private volatile Agir nesne;");
54        System.out.println("       public Agir get() {");
55        System.out.println("           Agir sonuc = nesne;");
56        System.out.println("           if (sonuc == null) {");
57        System.out.println("               synchronized (this) {");
58        System.out.println("                   sonuc = nesne;");
59        System.out.println("                   if (sonuc == null)");
60        System.out.println("                       nesne = sonuc = new Agir();");
61        System.out.println("               }");
62        System.out.println("           }");
63        System.out.println("           return sonuc;");
64        System.out.println("       }");
65        System.out.println("   Sorunlar: volatile unutulursa BUG; cok satirli, okunmasi zor;");
66        System.out.println("   JIT 'final' kadar iyi optimize edemez.\n");
67
68        System.out.println(">> YENI YONTEM: StableValue (PREVIEW)");
69        System.out.println("       private final StableValue<Agir> nesne = StableValue.of();");
70        System.out.println("       public Agir get() {");
71        System.out.println("           return nesne.orElseSet(() -> new Agir());");
72        System.out.println("       }");
73        System.out.println("   Avantajlar: tek satir, thread-safe, JIT 'final' gibi optimize");
74        System.out.println("   edebilir (constant folding). volatile/synchronized derdi yok.\n");
75        System.out.println("   NOT: API isimleri PREVIEW oldugu icin (StableValue.of /");
76        System.out.println("   orElseSet vb.) surumler arasi degisebilir; resmi JEP'e bakin.");
77    }
78
79    // ------------------------------------------------------------------------
80    //  GERCEK HAYAT: Konfigurasyon icindeki pahali bir baglanti dizesini
81    //  yalnizca ilk ihtiyac aninda, bir kez hesaplayip cache'lemek.
82    // ------------------------------------------------------------------------
83    static class Konfigurasyon {
84
85        // StableValue tutucusu: bir kez set edilir, sonra degismez.
86        // PREVIEW API'si: StableValue.of() bos bir tutucu olusturur.
87        private final StableValue<String> baglantiDizesi = StableValue.of();
88
89        String getBaglantiDizesi() {
90            // orElseSet: deger yoksa Supplier ile uretir+cache'ler, varsa cache'i dondurur.
91            // Supplier en fazla BIR KEZ calisir (thread-safe garantili).
92            return baglantiDizesi.orElseSet(this::agirHesaplama);
93        }
94
95        // Pahali hesaplamayi temsil eden metot.
96        private String agirHesaplama() {
97            System.out.println("   [AGIR HESAPLAMA calisiyor... bir kez]");
98            try {
99                Thread.sleep(300); // pahali I/O'yu simule et
100            } catch (InterruptedException e) {
101                Thread.currentThread().interrupt();
102            }
103            return "jdbc://veritabani:5432/uygulama?havuz=20";
104        }
105    }
106
107    // ------------------------------------------------------------------------
108    //  Referans: StableValue'yu bir Supplier gibi de kullanabilirsiniz.
109    //  Asagidaki yardimci, klasik Supplier imzasiyla nasil sarilabilecegini
110    //  gosterir (gercek API farkli yardimci metotlar sunabilir).
111    // ------------------------------------------------------------------------
112    @SuppressWarnings("unused")
113    static <T> Supplier<T> tembelSupplier(Supplier<T> kaynak) {
114        StableValue<T> sv = StableValue.of();
115        return () -> sv.orElseSet(kaynak);
116    }
117}
canlı çalıştırma için ortam gerekir

Bu sürüm-analizi örneği tek dosya olarak yerel JDK 21 ile çalıştırılamadı (bağımsız bir main içermeyebilir ya da daha yeni bir JDK / önizleme özelliği gerektirir). İlgili dil özelliği yukarıdaki anlatım ve kodda gösterilmiştir.

StructuredConcurrencyGuncel

ortam gerekir
StructuredConcurrencyGuncel.java
1// ============================================================================
2//  Java 25 - Structured Concurrency (JEP 505 - HALA PREVIEW)
3// ============================================================================
4//  DURUSTLUK NOTU: Structured Concurrency, Java 25'te HALA PREVIEW
5//  asamasindadir (JEP 505 - 5. preview). KALICI DEGILDIR. Bu nedenle:
6//      - --enable-preview ile derlemek/calistirmak gerekir,
7//      - API ileride degisebilir.
8//
9//  ONEMLI: API, son preview'larda DEGISTI. Eski "StructuredTaskScope.fork()
10//  + ShutdownOnFailure" yaklasimi yerine, Java 25'te (JEP 505) StructuredTaskScope
11//  bir "Joiner" (birlestirici) ile, genelde StructuredTaskScope.open(...) sekilde
12//  acilir. Asagidaki ornek, kavrami gostermek icin GUNCEL preview API tarzini
13//  kullanir. Surumunuzdeki KESIN imzalar icin resmi JEP 505'e bakin.
14//
15//  DERLEME / CALISTIRMA (Java 25 - PREVIEW):
16//      javac --release 25 --enable-preview StructuredConcurrencyGuncel.java
17//      java  --enable-preview StructuredConcurrencyGuncel
18//
19//  NEDIR:
20//    Structured Concurrency, ayni mantiksal isi yapan birden cok es zamanli
21//    alt gorevi TEK BIR birim gibi ele alir. Anladigimiz "yapisal programlama"
22//    mantigini (bir blok girilir, blok bitince her sey toparlanir) es zamanli
23//    gorevlere tasir:
24//      - Alt gorevler bir scope icinde acilir (fork edilir).
25//      - Biri basarisiz olursa digerleri OTOMATIK iptal edilir.
26//      - Scope bitmeden ana akis devam ETMEZ (sizan thread olmaz).
27// ============================================================================
28
29import java.util.concurrent.StructuredTaskScope;
30import java.time.Duration;
31
32public class StructuredConcurrencyGuncel {
33
34    public static void main(String[] args) throws Exception {
35        System.out.println("=== Java 25: Structured Concurrency (PREVIEW - JEP 505) ===\n");
36        System.out.println("(Calistirma: java --enable-preview StructuredConcurrencyGuncel)\n");
37
38        eskiYontemAciklama();
39
40        System.out.println("\n--- 1) BASARILI senaryo: birden cok servisten paralel veri ---");
41        try {
42            KullaniciProfili profil = profilGetir(42);
43            System.out.println("Birlesik profil -> " + profil);
44        } catch (Exception e) {
45            System.out.println("Hata: " + e.getMessage());
46        }
47
48        System.out.println("\n--- 2) HATA YAYILIMI / IPTAL senaryosu ---");
49        try {
50            profilGetirHataliServisIle(99);
51        } catch (Exception e) {
52            System.out.println("Beklenen davranis: bir gorev patlayinca digerleri iptal");
53            System.out.println("edildi ve hata yukari yayildi -> "
54                    + e.getClass().getSimpleName() + ": " + e.getMessage());
55        }
56    }
57
58    static void eskiYontemAciklama() {
59        System.out.println(">> ESKI YONTEM: ExecutorService + Future (yapisiz)");
60        System.out.println("   var ex = Executors.newFixedThreadPool(2);");
61        System.out.println("   Future<A> f1 = ex.submit(...);");
62        System.out.println("   Future<B> f2 = ex.submit(...);");
63        System.out.println("   A a = f1.get();   // f1 patlarsa f2 IPTAL EDILMEZ -> sizinti");
64        System.out.println("   B b = f2.get();   // iptal/zaman asimi yonetimi elle yapilir");
65        System.out.println("   Sorunlar: iptal yayilimi elle; thread sizintisi riski; hata");
66        System.out.println("   yonetimi dagilmis; iliski (parent/child) kaybolur.\n");
67
68        System.out.println(">> YENI YONTEM: StructuredTaskScope (PREVIEW)");
69        System.out.println("   try (var scope = StructuredTaskScope.open(...)) {");
70        System.out.println("       var t1 = scope.fork(() -> servisA());");
71        System.out.println("       var t2 = scope.fork(() -> servisB());");
72        System.out.println("       scope.join();          // ikisini birlikte bekle");
73        System.out.println("       return birlestir(t1.get(), t2.get());");
74        System.out.println("   } // blok bitince TUM alt gorevler toparlanir");
75        System.out.println("   Avantaj: biri patlarsa digeri otomatik iptal; sizinti yok;");
76        System.out.println("   hata ve iptal yapisal, okunabilir.\n");
77    }
78
79    // Basit modeller
80    record Temel(int id, String ad) {}
81    record SiparisOzeti(int adet, double toplam) {}
82    record KullaniciProfili(int id, String ad, int siparisAdet, double siparisToplam) {}
83
84    // ------------------------------------------------------------------------
85    //  1) BASARILI: iki servisten paralel veri cekip birlestirme.
86    //     NOT: Asagidaki StructuredTaskScope.open() ve Joiner kullanimi
87    //     Java 25 (JEP 505) preview API tarzini yansitir.
88    // ------------------------------------------------------------------------
89    static KullaniciProfili profilGetir(int kullaniciId) throws Exception {
90        // open(): tum alt gorevler basarili olursa devam, biri patlarsa hepsini iptal eder.
91        try (var scope = StructuredTaskScope.open(
92                StructuredTaskScope.Joiner.<Object>allSuccessfulOrThrow())) {
93
94            // Iki alt gorevi paralel baslat (sanal thread'lerde):
95            StructuredTaskScope.Subtask<Temel> temelGorev =
96                    scope.fork(() -> temelBilgiServisi(kullaniciId));
97            StructuredTaskScope.Subtask<SiparisOzeti> siparisGorev =
98                    scope.fork(() -> siparisServisi(kullaniciId));
99
100            // Hepsinin bitmesini bekle; biri patlarsa burada istisna firlar.
101            scope.join();
102
103            // Buraya gelindiyse ikisi de basarili:
104            Temel temel = temelGorev.get();
105            SiparisOzeti siparis = siparisGorev.get();
106            return new KullaniciProfili(
107                    temel.id(), temel.ad(), siparis.adet(), siparis.toplam());
108        }
109    }
110
111    // ------------------------------------------------------------------------
112    //  2) HATA YAYILIMI: siparis servisi patlar -> temel servis iptal edilir,
113    //     hata yukari yayilir.
114    // ------------------------------------------------------------------------
115    static KullaniciProfili profilGetirHataliServisIle(int kullaniciId) throws Exception {
116        try (var scope = StructuredTaskScope.open(
117                StructuredTaskScope.Joiner.<Object>allSuccessfulOrThrow())) {
118
119            scope.fork(() -> temelBilgiServisi(kullaniciId));
120            scope.fork(() -> hataliSiparisServisi(kullaniciId)); // patlar
121
122            scope.join(); // burada istisna firlar
123            throw new IllegalStateException("buraya ulasilmamali");
124        }
125    }
126
127    // --- Sahte servisler (paralel I/O simulasyonu) ---
128
129    static Temel temelBilgiServisi(int id) throws InterruptedException {
130        System.out.println("   [temel] cagrildi...");
131        Thread.sleep(Duration.ofMillis(200)); // ag gecikmesi simulasyonu
132        System.out.println("   [temel] tamam.");
133        return new Temel(id, "Kullanici-" + id);
134    }
135
136    static SiparisOzeti siparisServisi(int id) throws InterruptedException {
137        System.out.println("   [siparis] cagrildi...");
138        Thread.sleep(Duration.ofMillis(300));
139        System.out.println("   [siparis] tamam.");
140        return new SiparisOzeti(3, 1499.90);
141    }
142
143    static SiparisOzeti hataliSiparisServisi(int id) throws InterruptedException {
144        System.out.println("   [siparis-HATALI] cagrildi...");
145        Thread.sleep(Duration.ofMillis(100));
146        throw new RuntimeException("Siparis servisi cevap veremedi (HTTP 503)");
147    }
148}
canlı çalıştırma için ortam gerekir

Bu sürüm-analizi örneği tek dosya olarak yerel JDK 21 ile çalıştırılamadı (bağımsız bir main içermeyebilir ya da daha yeni bir JDK / önizleme özelliği gerektirir). İlgili dil özelliği yukarıdaki anlatım ve kodda gösterilmiştir.