Java 10, 11, 12 ile Gelen Yenilikler

tahaburak.koc
6 min readSep 16, 2019
Java

Merhaba, bu yazımda -bir öncekinin devamı olacak nitelikte- Java 10, 11, 12 ile hayatımıza giren birkaç yenilikten bahsedeceğim.

Bu yazıda birkaç Java versiyonunu birlikte almamın sebebi ise bu versiyonların (ve bundan sonra yayınlacak versiyonların) bir öncekiyle arasındaki yayınlanma sürenin çok daha kısalmış olması. Yazıdaki ilk maddede Java yayınlanma döngüsüne (Java Release Cycle) gelen bu değişiklikten bahsedeceğim.

Java 10

20.03.2018

Java Yayınlanma Döngüsü’ne gelen yenilik

Bundan önce yapılacak büyük yeniliklere göre yayınlanan Java versiyonları Java 10 ile birlikte 6 aylık bir döngüyle sunulmaya başlandı.

Birkaç versiyonun yayınlanma tarihini listelemek gerekirse:

  • Java 7 : 28.07.2011
  • Java 8 : 18.04.2014
  • Java 9 : 21.09.2017
  • Java 10 : 20.03.2018
  • Java 11 : 25.09.2018
  • Java 12 : 19.03.2019
  • Java 13 : 17.09.2019 (Beklenen tarih)

Yukarıdaki listede de görebildiğimiz üzere bundan önceki versiyonların yayınlanmaları arasında 2–3 yıla yakın bir süre vardı.

Bu durumun getirdiği birkaç dezavantaj var. Java sadece büyük yeniliklerle yeni versiyon yayınlıyor olsa da hem teknolojinin hem yönelimlerin gerektirdiği irili ufaklı birçok yenilik de bu versiyonlar ile sunuluyordu. Bu durum, hem küçük yeniliklerin mecburen bir sonraki versiyona ertelenmesine sebep hem de adaptasyonu zorlaştırmaktaydı.

Örneğin yeni bir Java sürümü çıkana kadar zaten bir geliştirici, bir takım hatta bir şirket zaten yayınlanmış versiyonu benimseyip projelerinde kullanmış olduğu için yeni versiyona geçiş için büyük efor ve alınması gereken riskler ortaya çıkıyordu. Gelen yenilik ne kadar büyük olursa olsun eldeki projeye ne kadar katkı sağladığı değişken bir durum olduğu için, hem bu geçişe kaynak ve vakit ayırmak hem de zaten çalışmakta olan bir sisteme büyük bir katkısı yokken böyle bir güncelleme yapmak pek de tercih edilmiyordu. (En azından ben böyle olmuştur diye düşünüyorum.)

Java Release Timeline

Lokal Değişken: Var

Çeşitli programlarında(Javascript, Go, Swift vb.) kullanılan var ifadesi bu versiyon ile Java’ya da gelmiş oldu. Bu ifade özetle, objenin hangi sınıftan olduğunu belirtmemiz gerekmeden tanımlama yapmamızı sağlamakta.

// Before Java 10 String text = "123";
Integer number = 123;
Map<Integer, String> map = new HashMap<>();
// After Java 10var text = "123;
var number = 123;
var map = new HashMap<Integer, String>();

String ve Integer örneklerinin aksine HashMap örneğinde sadece objenin önündeki ifadeyi değiştirmedik. var ifadesini kullanabilmemiz için birkaç kurala uymamız gerekmekte.

Öncelikle var ifadesinin kullanılmasıyla ilgili tüm yönlendirmeleri şu adresten bulabilirsiniz : https://openjdk.java.net/projects/amber/LVTIstyle.html. Fakat temeldeki durum şu: Developer belirtmese dahi compiler objenin türünden emin olmalı.

Örneklerle ilerlemek gerekirse:

illegal use of var keyword

Önemli bir diğer konu ise var ifadesinin rezerve edilmiş bir ifade olmaması. String, int gibi ifadeleri rezerve edilmiş olduğu için değişken ismi atayamıyorken bu durum var için geçerli değil. Yani önceden var ismini verdiğimiz paket, method ve değişken isimlerinde değişikliğe gitmemiz gerekmemekte.

Ekstra bir bilgi olarak:

var ifadesini kullanan programlama dillerde genellikle değiştirilemez halini karşılayacak bir başka ifade daha bulunmakta. Javascript ve Swift için let, Scala ve Kotlin için val gibi. Yapılan anketler ve araştırmalar sırasında kimilerinin let kimilerininse val kullanmayı istemediği ortaya çıkmış. Java’da bu durumu karşılamak için final var kullanımına yöneliyoruz.

Değiştirilemez Collection Geliştirmeleri

Java 10 ile gelen Collection sınıflarına çeşitli methodlar getirildi.

  • java.util.List, java.util.Map, java.util.Set sınıflarına copyOf(Collection) methodları getirildi. Bu methodlar ile bir List objesinden aynı objelere sahip fakat yeni bir obje eklenmesi veya var olan bir objenin çıkarılması sırasında UnsupportedOperationException hatası fırlatan yeni bir List objesi üretilebilir.
copyOf(Collection)
  • java.util.stream.Collectors sınıfına gelen to toUnmodifiableList() methoduyla da aynı şekilde değiştirelemeyen bir List, Map veya Set objesi üretebiliriz.
toUnmodifiableList()

Optional sınıfında orElseThrow() methodu

Java 10 ile birlikte java.util.Optional, java.util.OptionalDouble, java.util.OptionalInt, java.util.OptionalLong objelerinde orElseThrow() methodu kullanarak istenen filtreye uygun obje bulunamaması halinde NoSuchElementException hatası fırlatabiliriz.

orElseThrow()

Container Farkındalığı

Java 10 ile birlikte JVM üzerinde container için çeşitli parametreler sağlayabiliyoruz.

Öncelikle aşağıdaki parametrenin true şeklinde geçmesi gerekmekte (varsayılan değeri true olduğu için belirtmek zorunda değiliz.):

-XX:-UseContainerSupport

JVM’in kullanacağı CPU sayısını aşağıdaki parametre ile belirtebiliriz:

-XX:ActiveProcessorCount=count

Docker container’ı için geçebileceğimiz birkaç parametre ise şu şekilde:

-XX:InitialRAMPercentage-XX:MaxRAMPercentage-XX:MinRAMPercentage

Java 11

25.09.2018

Tekil-Dosya Kaynak Kodu (Single-File Source Code)

Java 11 ile beraber tek bir Java dosyasını öncesinde javac komutu kullanmadan çalıştırabilir hale geldik.

// Before Java 11
$
javac HelloWorld.java
$ java HelloWorld
Hello World!
// After Java 11
$
java HelloWorld.java
Hello World!

JDK java komutu ile çalıştırdığımız bu dosya içerisindeki ilk main methodu bulacak ve (eğer varsa) verilmiş paramatreler ile bu methodu çalıştıracaktır. Elimizde aşağıdaki gibi bir Addition.java dosyasını olduğunu varsayalım:

Bu dosyayı çalıştırmak için gerekecek komut ve çıktısı şu şekilde olacaktır:

$ java Addition.java 1 2 36

Shebang Dosyaları

Yukarıdaki yenilik ile Unix tabanlı işletim sistemlerinde yaygın şekilde kullanılan script yapısını kullanabilir hale geldik. İçeresinde kendisinin neye göre çalıştıralacağı belirtilen ve script şeklinde çalıştırabileceğimiz dosyalara Shebang dosyaları denmekte.

Örneğin aşağıdaki gibi add isimli bir dosyamız olduğunu varsayalım:

Shebang example

Bu dosyayı çalıştırabilir hale getirmek için aşağıdaki komutu çalıştırıyoruz:

$ chmod +x add

Bu dosyayı çalıştırmak için gerekecek komut ve çıktısı şu şekilde olacaktır:

$ ./add 1 2 36

String API Üzerindeki Yenilikler

  • repeat(int) methodu:

int parametresi ile çalıştırdığımız bu parametre ile ilgili String objesinin kaç defa tekrarlanacağını belirtebiliyoruz. Bu objenin boş olması veya parametre olarak 0 verilmesi halinde boş String döndürülmektedir.

repeat(int)
  • isBlank() methodu:

İlgili String objesinin boş olması veya sadece whitespace karakter içermesi halinde true, diğer durumlarda ise false döndüren bir method.

isBlank()
  • strip(), stripLeading(), stripTrailing() methodları:

İlgili String objesi içerisindeki whitespace karakterleri kaldırarak bir String objesi döndürür.

strip()

stripLeading() methodu String objesinin içerisindeki ilk whitespace olmayan karakter öncesindeki whitespace karakterlerini kaldırırken stripTrailing() methoduysa bu işlemi sonrasındaki karakterler için uygular.

Zaten var olan trim() methodundan ayrıldığı nokta ise trim() methodunun Unicode whitespace karakterleri algılayıp silememesi. Örnek:

strip() vs trim()
  • lines() methodu:

Bu methodu ile ilgili String objesinin satırlarını Stream objesi olarak döndürebiliriz. lines() methodunun satır belirlemede kullandığı ifadeler ise şu şekilde : “\n”, “\r”, or “\r\n”.

lines()

Java 12

19.03.2019

switch İfadesi Üzerindeki Yenilik

Java 12'de göze en çok çarpan yenilik switch ifadesinin kullanımı üzerinde oldu. Java 12 ile birlikte switch ifadesini değer döndürecek şekilde kullanabilir hale geldik.

Görebileceğimiz üzere yeni halinde daha güvenli(break eklemeyi unutma gibi bir hataya mahal vermiyor) ve kolay şekilde yazabiliyoruz.

Ayrıca switch içerisinde enum kullanmışsak default case yazmamız gerekmemekte fakat tüm enumları kullanmamışsak compile-time hatası ile karşılaşıyoruz. Bunun yanısıra case sonrasında { } kullanarak yeni bir lokal scope açıp daha kompleks işlemler gerçekleştirebiliriz.

Stream API Üzerindeki Yenilikler

  • teeing(Collector, Collector, BiFunction) methodu:

Java 12 ile java.util.stream.Collectors sınıfına eklenen teeing(Collector, Collector, BiFunction) methodu ile iki Collector sınıflı objeyi kullanarak bu objeler üzerinde çeşitli işlemler yapıp bu sonucu ayrı bir Collector objesi olarak döndürebiliriz.

teeing()
teeing() example

Örneğin yukarıdaki methodtaki summingDouble(i -> i) methodu ile Stream içerisinde verilen değerler toplanırken counting() ile de kaç değer verildiği sayılmaktadır. teeing() methodu ile verdiğimiz 3.parametreyle ile ise bu iki collector methodunun sonuçları bölme işlemine sokularak ortalama değere ulaşılmıştır.

Ortalamayı bulmak için çok daha kolay yollar olsa da bu örneğin amacı teeing() ile sadece bir kere değer seti vererek iki farklı collector ve bunları kullanan bir başka method kullanmış olmamız.

Bu yazıyı hazırlarken kullandığım ve/veya faydalı olabilecek birkaç link bırakarak yazımı sonlandırıyorum, iyi okumalar.

Create and share beautiful images of your source code.

Guide to Java 10

Java 10 LocalVariable Type-Inference

Java 11 Single File Source Code

Java 11 String API Additions

Java 12: New Features and Enhancements Developers Should Know

JDK 12 Switch Expression — Preview Feature

--

--