Java 16 Yenilikleri (2021)
Java 16, önceki sürümlerin iki büyük önizleme özelliğini standartlaştırdı: records ve pattern matching for instanceof. Ayrıca pratik stream eklemeleri (toList, mapMulti) getirdi. Bu, Java 17 LTS'e giden yolun son adım…
Java 16 Yenilikleri (2021)
Java 16, önceki sürümlerin iki büyük önizleme özelliğini standartlaştırdı: records ve
pattern matching for instanceof. Ayrıca pratik stream eklemeleri (toList, mapMulti) getirdi.
Bu, Java 17 LTS'e giden yolun son adımıydı — 17'de sealed sınıflar da standartlaşarak modern Java'nın
çekirdek dil özellikleri tamamlandı.
records standart
Java 14-15'te önizleme olan record, Java 16'da standart oldu. Değişmez veri sınıflarını tek
satıra indirir; equals/hashCode/toString ve getter'lar otomatik üretilir:
record Para(long kurus, String birim) { Para { // kompakt kurucu: doğrulama/normalizasyon if (kurus < 0) throw new IllegalArgumentException("negatif olamaz"); birim = birim.toUpperCase(); } double tutar() { return kurus / 100.0; } // ek metot static Para tl(double t) { return new Para(Math.round(t*100), "TRY"); } // statik fabrika }
Record'lar bir arayüz uygulayabilir, ek/statik metot içerebilir ve bir metot içinde yerel
record olarak tanımlanabilir. Ama alan ekleyemez (durumu yalnızca bileşenleridir) ve başka sınıfı
uzatamaz. Örnek 1 (./Ornek1.java) kompakt kurucu, statik fabrika, arayüz ve yerel record gösterir.
(Records'ı topic 37/62'de ve veri modellemede sık kullanıyoruz; DTO/değer nesneleri için idealdir.)
pattern matching for instanceof standart
Java 14'te önizleme olan bu özellik Java 16'da standart oldu:
if (o instanceof String s) return s.length(); // kontrol + cast + bağlama tek adımda
Eski instanceof + ayrı cast kalıbını ortadan kaldırır. Örnek 2 (./Ornek2.java) bunu gösterir.
Stream eklentileri
Stream.toList():collect(Collectors.toList())için kısa yol. Değişmez bir liste döndürür (dikkat: eskisi değiştirilebilirdi).Stream.mapMulti(fn): Her elemanı sıfır/bir/çok elemana genişletir —flatMap'e alternatif. Eleman başına az sayıda çıktı üretiliyorsa, araStreamnesneleri oluşturmadığı içinflatMap'ten daha verimli olabilir:
Stream.of(1,2,3).<Integer>mapMulti((n, tuket) -> { tuket.accept(n); tuket.accept(n*10); }).toList(); // [1, 10, 2, 20, 3, 30]
Örnek 2 her ikisini de gösterir.
Sürüm batch'inin sonu (8 → 16) ve sonrası
Bu konuyla, listenizdeki Java 8 → 16 sürüm-sürüm yenilikleri tamamlandı. Bu özelliklerin çoğu Java 17 (LTS) ve 21 (LTS) ile olgunlaştı:
- Java 17 (LTS): sealed sınıflar standart.
- Java 21 (LTS): record patterns, switch pattern matching, virtual threads, sequenced collections (topic 20 Ornek4'te gördük).
Yani 8-16 arası attığın her adım, bugünün modern Java'sının (17/21) temelini oluşturur.
Özet
Java 16'nın yeniliklerini öğrendik: standartlaşan records (kompakt kurucu, statik fabrika, yerel
record; Örnek 1) ve pattern matching instanceof, ayrıca Stream.toList ve mapMulti
(Örnek 2). Bununla sürüm-sürüm bölümü (Java 8→16) tamamlandı; bu özellikler 17/21 LTS'lerde
olgunlaşarak modern Java'yı şekillendirdi. Sırada — bir sonraki büyük bölüm — Java'nın klasik
GUI/web teknolojilerine giriş: Swing, AWT, Servlet, JSP.
▶ Kod Örnekleri(2)
Ornek1
çalıştırılabilir1// Ornek1: Java 16 — records STANDART (kompakt kurucu, statik fabrika, metot, arayüz).
2// Çalıştırma: java Ornek1.java
3public class Ornek1 {
4
5 interface Bilgilendirilebilir { String ozet(); }
6
7 // record: değişmez veri taşıyıcısı. equals/hashCode/toString/getter'lar OTOMATİK.
8 record Para(long kurus, String birim) implements Bilgilendirilebilir {
9
10 // KOMPAKT KURUCU: doğrulama/normalizasyon için (alan atamaları otomatik).
11 Para {
12 if (kurus < 0) throw new IllegalArgumentException("negatif tutar olamaz");
13 birim = birim.toUpperCase(); // normalize
14 }
15
16 // Ek (türetilmiş) metot
17 double tutar() { return kurus / 100.0; }
18
19 // Statik fabrika metodu
20 static Para tl(double t) { return new Para(Math.round(t * 100), "TRY"); }
21
22 // Arayüz metodu
23 @Override public String ozet() { return String.format("%.2f %s", tutar(), birim()); }
24 }
25
26 public static void main(String[] args) {
27 Para p1 = Para.tl(19.99);
28 Para p2 = new Para(1999, "try"); // birim normalize -> TRY
29 System.out.println("p1: " + p1 + " | ozet: " + p1.ozet());
30 System.out.println("p1.equals(p2)? " + p1.equals(p2) + " (değer eşitliği — otomatik)");
31 System.out.println("getter: kurus=" + p1.kurus() + ", birim=" + p1.birim());
32
33 try {
34 new Para(-5, "TRY");
35 } catch (IllegalArgumentException e) {
36 System.out.println("kompakt kurucu doğruladı: " + e.getMessage());
37 }
38
39 // Yerel (local) record — bir metot içinde geçici veri gruplamak için (Java 16).
40 record Nokta(int x, int y) {}
41 Nokta n = new Nokta(3, 4);
42 System.out.println("yerel record: " + n + ", uzaklık=" + Math.hypot(n.x(), n.y()));
43
44 System.out.println("""
45
46 --- Java 16: records standart ---
47 record, değişmez veri sınıflarını tek satıra indirir; equals/hashCode/toString/getter OTOMATİK.
48 Kompakt kurucu (Para { ... }): doğrulama ve normalizasyon için (alan atamaları örtük).
49 Ek metot, statik fabrika, arayüz uygulama desteklenir; YEREL record da olabilir.
50 (14-15'te önizleme, 16'da standart.) DTO/değer nesneleri için idealdir.""");
51 }
52}Ornek2
çalıştırılabilir1// Ornek2: Java 16 — pattern matching instanceof STANDART, Stream.toList() ve Stream.mapMulti.
2// Çalıştırma: java Ornek2.java
3import java.util.List;
4import java.util.stream.Stream;
5
6public class Ornek2 {
7
8 public static void main(String[] args) {
9 // 1) pattern matching for instanceof artık STANDART (Java 16).
10 Object[] nesneler = { "merhaba", 42, List.of(1, 2, 3), 3.14 };
11 for (Object o : nesneler) {
12 String s = tanim(o);
13 System.out.println(o + " -> " + s);
14 }
15
16 // 2) Stream.toList(): collect(Collectors.toList()) için kısa yol (değişmez liste döndürür).
17 List<Integer> kareler = Stream.of(1, 2, 3, 4).map(n -> n * n).toList();
18 System.out.println("\ntoList(): " + kareler);
19
20 // 3) Stream.mapMulti: her elemanı SIFIR/BİR/ÇOK elemana genişlet (flatMap'e alternatif, daha az nesne).
21 List<Integer> genisletilmis = Stream.of(1, 2, 3).<Integer>mapMulti((n, tuket) -> {
22 tuket.accept(n); // elemanın kendisi
23 tuket.accept(n * 10); // ve 10 katı
24 }).toList();
25 System.out.println("mapMulti (n ve 10n): " + genisletilmis);
26
27 System.out.println("""
28
29 --- Java 16: pattern matching standart, toList, mapMulti ---
30 pattern matching instanceof: 'if (o instanceof String s)' artık STANDART (önizleme değil).
31 Stream.toList(): .collect(Collectors.toList()) yerine kısa; DEĞİŞMEZ liste döndürür.
32 Stream.mapMulti(fn): her elemanı 0/1/çok elemana genişletir (flatMap benzeri ama daha az
33 ara nesne üretir; eleman başına çok az çıktı varken daha verimli).""");
34 }
35
36 static String tanim(Object o) {
37 // pattern matching instanceof — kontrol + cast + bağlama tek adımda.
38 if (o instanceof String str) return "String(" + str.length() + ")";
39 if (o instanceof Integer i) return "Integer(kare=" + (i * i) + ")";
40 if (o instanceof List<?> liste) return "List(boyut=" + liste.size() + ")";
41 return o.getClass().getSimpleName();
42 }
43}