Java 9 – Modüler Sistem, REPL ve Yeni API’ler

Java 9 – Modüler Sistem, REPL ve Yeni API’ler

Java 9, Java 8’in sunduğu fonksiyonel programlama, Lambda, Stream, Date-Time API gibi büyük yeniliklerin üzerine; mimari temizleme, modüler yapı, API kullanım kolaylığı ve dilsel küçük ama etkili iyileştirmeler getiriyor. Eğer hâlâ Java 8 kullanıyorsan, bazı projelerde Java 9’a geçmek kodlarının daha temiz, bakımı daha kolay ve mimarisi daha sürdürülebilir olmasını sağlayabilir.

Java 9 ile Gelen Özellikler

Java 9, kodun modüllere ayrılmasını sağlayan bir modüler sistem getiriyor. JDK da modüller hâline geldi; hangi modülün hangi modüllere bağımlı olduğu (requires), hangi paketlerin dışa açıldığı (exports), hangi modüllerin erişimine kapalı olduğu gibi sınırlar netleşti. Böylece uygulamalar ve JDK kendisi daha güvenli, daha yönetilebilir ve daha hafif yapılara sahip olabiliyor.

module com.example.myapp {
    requires java.sql;          // bu modül java.sql modülüne ihtiyaç duyar
    exports com.example.myapp.api;  // bu paketi dışarı açar
}
module com.example.db {
    exports com.example.db.impl;     // iç implementasyonu dışa sunar
}
javac --module-source-path src -d out $(find src -name "*.java")
java --module-path out --module com.example.myapp/com.example.myapp.Main

JShellREPL (Read–Eval–Print Loop)

Java artık etkileşimli bir kabuk (REPL) ortamına sahip. Küçük kod parçalarını doğrudan çalıştırmak, fikirleri hızlıca test etmek ya da sınıf/method yazmadan denemeler yapmak için çok kullanışlı.

jshell> int x = 5 * 7
x ==> 35

jshell> String s = "Merhaba Java 9"
s ==> "Merhaba Java 9"

jshell> s.substring(8)
$3 ==> "Java 9"

Immutable Collection’lar için Factory Metotları

Java 8’de immutable koleksiyon oluşturmak için Collections.unmodifiableList(...) gibi daha dolaylı yollar kullanılıyordu. Java 9’da List.of(...), Set.of(...), Map.of(...), Map.ofEntries(...) gibi metodlarla daha kısa ve temiz immutable koleksiyonlar oluşturmak mümkün.

import java.util.List;
import java.util.Set;
import java.util.Map;

public class ImmutableCollectionsExample {
    public static void main(String[] args) {
        List<String> liste = List.of("elma", "armut", "muz");
        // liste.add("kiraz"); // UnsupportedOperationException

        Set<Integer> set = Set.of(1, 2, 3, 4);

        Map<String, Integer> map = Map.of(
            "bir", 1,
            "iki", 2,
            "üç", 3
        );
        System.out.println(liste);
        System.out.println(set);
        System.out.println(map);
    }
}

Dil (Language) Geliştirmeleri

Aşağıdakiler kod okunabilirliği, yeniden kullanım ve kodun daha temiz olması açısından önemli değişiklikler:

  • 👉 Interface’lerde Private Metotlar
    Default metodlar içinde ortak işler varsa bunları private metodlarla soyutlayıp kod tekrarını azaltmak mümkün. Ayrıca static private metodlar da var.
public interface Hesaplama {
    default int toplama(int a, int b) {
        validate(a, b);
        return a + b;
    }

    default int carpma(int a, int b) {
        validate(a, b);
        return a * b;
    }

    private void validate(int a, int b) {
        if (a < 0 || b < 0) {
            throw new IllegalArgumentException("Negatif değer olamaz");
        }
    }
}
  • 👉 Try-with-resources İyileştirmesi
    Java 9’dan önce her kaynak (resource) için try parantezleri içinde yeni değişken oluşturmak gerekiyordu. Java 9 ile, kaynak olarak kullanılacak nesne final ya da effectively final ise doğrudan kullanılabiliyor.
class Kaynak implements AutoCloseable {
    public void close() {
        System.out.println("Kaynak kapatıldı");
    }
    public void doWork() {
        System.out.println("İş yapılıyor");
    }
}

public class TryWithResourcesExample {
    public static void main(String[] args) {
        Kaynak k = new Kaynak();
        try (k) {
            k.doWork();
        }
    }
}
  • 👉 Diamond Operatörü Anonim Sınıflarla Kullanımı
    Anonim (anonymous) inner class’larda diamond (<>) operatörü kullanılabiliyor hale geldi. Bu, generics kullanımında kodu biraz kısaltıyor.
import java.util.Comparator;

public class DiamondAnonymousExample {
    Comparator<String> cmp = new Comparator<>() {
        @Override
        public int compare(String s1, String s2) {
            return s1.length() - s2.length();
        }
    };
}

Stream & Optional API’deki Geliştirmeler

Java 9, Stream ve Optional sınıflarında bazı yeni metodlar getirerek işlevselliği artırdı.

  • 👉 Stream API: takeWhile, dropWhile, ofNullable, iterate’in yeni overload’ları gibi.
  • 👉 Optional: ifPresentOrElse(), or() gibi yeni metodlarla, Optional değerleriyle çalışmak daha esnek hâle geldi.
import java.util.*;
import java.util.stream.*;

public class StreamOptionalExample {
    public static void main(String[] args) {
        // Stream.takeWhile / dropWhile
        Stream<Integer> seq = Stream.of(1, 2, 3, 4, 5, 6);
        seq.takeWhile(n -> n <= 3)
           .forEach(n -> System.out.println("takeWhile: " + n));

        seq = Stream.of(1, 2, 3, 4, 5, 6);
        seq.dropWhile(n -> n <= 3)
           .forEach(n -> System.out.println("dropWhile: " + n));

        // ofNullable
        Stream<String> maybe = Stream.ofNullable(null);
        System.out.println("maybe count: " + maybe.count());

        // Optional
        Optional<String> opt = Optional.of("Java9");
        opt.ifPresentOrElse(
          s -> System.out.println("Var: " + s),
          () -> System.out.println("Yok!")
        );

        Optional<String> fallback = opt.or(() -> Optional.of("Varsa fallback"));
        System.out.println("or() sonucu: " + fallback.get());
    }
}

Process API Geliştirmeleri

Java 9 ile işletim sistemi süreçleri (processes) ile ilgili daha detaylı kontrol ve bilgilere erişim sağlanıyor. Örneğin:

  • 👉 Mevcut sürecin PID’si alınabiliyor.
  • 👉 Başlangıç zamanı, CPU süresi gibi bilgiler ProcessHandle üzerinden okunabiliyor.
  • 👉 children() ve descendants() metodları ile alt süreçler/fonksiyon çağrıları takip edilebiliyor.
import java.time.Duration;
import java.time.Instant;

public class ProcessApiExample {
    public static void main(String[] args) {
        ProcessHandle current = ProcessHandle.current();
        long pid = current.pid();
        ProcessHandle.Info info = current.info();

        System.out.println("PID: " + pid);
        info.startInstant().ifPresent(start -> System.out.println("Başlangıç: " + start));
        info.totalCpuDuration().ifPresent(cpu -> System.out.println("CPU süresi: " + cpu));

        // Alt süreçler
        current.children().forEach(child -> 
            System.out.println("Child process ID: " + child.pid())
        );
    }
}

👉 Sıradaki yazımızda Java 9 ile gelen Modüler Sistem ve diğer yeniliklere göz atacağız:
➡️ Java 10 – Local Variable Type Inference (var)


📝 Kaynaklar:

Codest Blog

Codest Blog yazılım hakkında her konuda bilgi sağlayan bir blog sitesidir. Bilgi paylaştıkça güzeldir felsefesi ile hareket ederek, yazılımcıların en cok karşılaştığı konuları sizlere aktarmayı hedefliyoruz. Keyifli okumalar 🙂