Java 8'den 11'e Yenilikler

Nailcan Küçük
İyi Programlama
Published in
4 min readNov 14, 2019

İlk Beta sürümü 1995 yılında tanıtıldıktan sonra 1.0 versiyonu 1996, Ocak ayında yayınlanan Java, 2006 yılındaki Java 6 versiyonuna kadar neredeyse 2 yılda bir yeni bir ana versiyon ile karşımıza çıkmıştı. Fakat bir sonraki versiyon olan Java 7 için 5 yıl beklememiz gerekti ve 2011 yeni versiyon ile tanışabildik.

2014, Mart ayında yayınlanan Java 8 sonrası Oracle firması versiyon politikasında değişikliğe gitti. Bu politikaya göre kısa süreli destek alacak olan geçiş versiyonları ve uzun süreli destek alacak (LTS) ana versiyonlar yayınlanmasına karar verildi. Artık ara versiyonlara bir sonraki ara veya LTS versiyon çıkana kadar destek verilecektir.

Eylül 2017’de Java 9 ve Mart 2018’de Java 10 yayınlandıktan sonra şu anda hali hazırda en güncel ana versiyon olan Java 11 Eylül 2018’de bizlerle buluştu.

Ben bu yazıyı yazarken ise son versiyon olarak Eylül 2019’da yayınlanan Java 13 kullanılmakta.

Java versiyonları ile ilgili bu ön girizgahtan sonra bu yazının ana konusuna artık hafiften geçebiliriz. Son 2 ana sürümler Java 8’den Java 11’e geçişte bize sunulan yeniliklerden en önemli gördüklerime kısaca sıra ile değineceğim.

# Modularization — Project Jigsaw
Java 9 ile hayatımıza giren Jigsaw Projesi monolitik uygulamaları modüllere ayırabilmemizi sağlamaktadır. Aynı amaca hizmet eden sınıflar bir source root altında toplanarak uygulama içerisinde birçok farklı modül oluşturulabilir.

Modülerlik, monolit mimarideki uygulama ile microservice mimarisindeki uygulamalar arasında bir ara faz olarak görülebilir belkide. Her bir modül kendine özgü tek bir işi yapacak şekilde ihtiyacı olan tüm katmanları barındırabilir. Bu da monolit uygulama içerisinde kendi sorumluluğu olan bir çok modül oluşturulabilmesi anlamına geliyor. Daha sonrasında bu monolitik uygulamayı microservice mimarisine geçirmek de daha kolay olacaktır.

Modüller arası erişilebilirlik ise modül ana dizini seviyesinde bulunan module-info.java sınıfı içerisinde tanımlanır.

Diyelim ki projemiz içerisinde com.demo.sql ve com.demo.audit isimli 2 tane modülümüz olsun. sql modülümüz içerisinde de connection ve crud isimli 2 paketimiz olsun.

sql modülü içerisindeki connection paketine diğer modüller tarafından erişilmesini istemiyoruz ancak crud paketini erişilebilir yapmak istiyorsak module-info.java sınıfı aşağıdaki gibi olmalıdır.

module sql {
exports com.demo.sql.crud;
}

Diyelim ki audit modülü sınıfları içerisinde sql.crud paketi altındaki sınıflara erişim var. Bu durumda audit paketinin module-info.java sınıfında bu bağımlılık yine aşağıdaki gibi tanımlanmalıdır.

module audit {
requires com.demo.sql.crud;
}

Java 9 içerisinde java.base, java .desktop, java.naming, java .sql … gibi yaklaşık 40 standart modül ile birlikte gelmektedir. Bu modülleri $JAVA_HOME/jmods klasörü altında görebiliriz.

Daha detaylı bilgi almak için burayı inceleyebilirsiniz.

# JEP 330: Launching Single Source File Programs
Java 11’den önce main metoduna sahip bir java class’ını console üzerinde çalıştırabilmek için ilk önce bu sınıfı compile etmek daha sonra da çalıştırmak gerekiyordu.

class Test {
public static void main(String… args) {
System.out.println(“Application running…”);
}
}

Yukarıdaki sınıfı çalıştırmak için aşağıdaki komutları sırası ile çalıştırmak gerekiyordu.

$javac -d classes Test.java
$java cp classes Test

Java 11 ile artık Test sınıfımızı compile etmeden aşağıdaki gibi tek satırda çalıştırabiliyoruz.

$java Test.java

# JEP 328: Java Flight Recorder
JVM üzerinde uygulama çalışırken uygulamayı en düşük seviyede izleyebilmek için bir araç.

Geliştirme ortamında lokal makinemizde her sorunu tam olarak analiz edemeyebiliyoruz. Örneğin uygulamada memory leak oluşma ihtimali varsa ve bu da 4 5 gün sürüyorsa, bu sorunu production ortamında görmek daha mümkün. Production ortamında memory leak oluştuğu zaman Flight Recorder bunu kaydediyor ve daha sonrasında kontrol ederek bu sorunun nereden kaynaklandığını anlamak kolaylaşıyor.
— XX:StartFlightRecording parametresi ile aktif ediliyor.

# JEP 333: ZGC

Yeni ve daha performanslı bir Garbage Collector yapısıdır. Temel iyileştirmelerinin ölçekleri aşağıdaki gibidir.
- Terabyte seviyesinde HEAP
- Maksimum 10ms duraklama süresi
- Maksimum %15 uygulama verim düşüklüğü

# JEP 286: Local-Variable Type Interface (Java 10)
Artık parametre tanımlarken parametre tipi belirtmeden, sadece `var` keyword ile tanımlama yapabiliyoruz.

Nerelerde kullanılabilir:
- Varsayılan değeri olan yerel değişkenleri tanımlarken
- `for` döngüsü içerisinde kullanılabilir

var testWord = “Hello, Test”;
var age = 22;
var isAvailable = true;
for(var i = 0; i < 10; i++)
for(var user: users)

Nerelerde kullanmamalıyız:
- Varsayılan değer atamadığımız parametreleri tanımlarken
- Varsayılan değeri null olan parametre tanımlarken
- Dizi tanımlarken
- Metod parametresi tanımlarken
- Metod geri dönüş tipi olarak

var test;
var test = null;
var test = {0,1,2,};
public void get(var id);
public var get(Long id);

# JEP 323: Local-Variable Syntax for Lambda Parameters
Lambda tanımlamaları daha önce explicitly ve implicitly olarak 2 şekilde yapılabilmekteydi. Artık implicitly olarak `var` kullanarak tanımlayabiliyoruz.

(Item a, int b) -> a.create(b); // Explicitly
(a,b) -> a.create(b); // Implicitly
(var a, var b) -> a.create(b); // Implicitly with var

var kullanımından önce lambda expression içerisinde notasyon kullanmak istiyorsak explicitly olarak tanımlamamız gerekmekteydi. Artık var kullanımı ile implicitly tanım da yapabiliyoruz.

(@Nonnull var a, var b) -> a.create(b);

Explicitly ve implicitly tiplerin beraber kullanımı doğru değildir.

(Item a, b) -> a.create(b);
(var a,b) -> a.create(b);
(var a, int b) -> a.create(b);

# JShell

Java 9 ile gelen REPL aracıdır. Jshell sayesinde artık komut satırı üzerinde java kodu yazıp çalıştırabiliyoruz. Bu sayede kod yazdığımız dosyaları derleme ve sonrasında çalıştırma süreci yerine, hemen terminal üzeriden yazıp kodumuzun çıktısını görebiliyoruz.

Detaylı bilgi için aşağıdaki karta tıklayarak Oracle’ın sayfasındaki Jshell ile ilgili dökümana erişebilirsiniz.

# Optional - Yenilikler

ifPresentOrElse(): Optional.isPresent() metoduna göre if-else yazmak yerine tek metod ile if ve else koşullarındaki çalışmasını istediğimiz metodları tanımlayabiliyoruz.

if (optionalPrice.isPresent()) {
updatePrice(optionalPrice.get());
} else {
finishOperation();
}
-----------
optionalPrice.ifPresentOrElse(this::updatePrice, this::finishOperation);

or(): Optional dönen bir metod çağırıldığında, sonucun Optional.empty() olması durumuna göre davranış tanımlanabilmesini sağlamaktadır.

Optional<Person> optionalPerson = findPersonById(1L).or(() -> Optional.of(new Person()));

# CompletableFeature - Yenilikler

orTimeout(): CompletableFeature nesnesi akış içerisinde verilen timeout süresi içerisinde completed olmazsa hatalı olarak (exceptionally) completed olmaktadır.

CompletableFuture<String> cf = future.orTimeout(30, TimeUnit.SECONDS);

completeOnTimeout(): CompletableFeature nesnesi akış içerisinde verilen timeout süresi içerisinde completed olmaz ise verilen varsayılan değer ile completed olmaktadır.

CompletableFuture<String> cf = future.completeOnTimeout("Default completed value",30, TimeUnit.SECONDS);

Java 11 ve 8 versiyonları arasında bulunan onlarca değişiklikten gözüme çarpan bir kaçını kısaca özetlemeye çalıştım.

Java 11 ile ilgili Oracle firmasının hazırladığı döküman sayfasına aşağıdaki karttan erişerek daha detaylı bilgi edinebilirsiniz.

--

--