Java 14'de neler var - 1



Java 14 sürümü 17 Mart tarihi itibariyle kullanıma sunuldu. Ben de bir süredir Jdk'daki yeniliklerden uzak kaldığım için kendimi de güncellemek amaçlı OpenJDK sitesinde listelenen yenilikleri gözden geçirdim. Yaptığım çalışmaları da hem kod hem de yorumlarım ile paylaşıyorum.

Java14 kullanmak isterseniz Oracle ve AdoptOpenJdk'dan indirebilirsiniz. Diğer dağıtıcılar da zamanla hazır olacaklardır.

Yeni eklenen özelliklerin bir kısmı kodlama ile ilgiliyken bir kısmı da Jvm ya da araçlar ile ilgili.

Yenilikler JEP - JDK Enhancement Proposal ler üzerinden takip ediliyor ve bu sürümde 16 tane JEP eklenmiş. Bunlardan üç tanesi Preview - Ön izleme 2 tanesi ise Incubator - kuluçka etiketi ile sunulmuş.

JEP-305 : Pattern Matching for instanceof (Preview) [Ref]

Daha önce instanceof operatörü kullanırken test ettiğimiz nesne tipi eğer istediğimiz nesnenin bir türevi ise kullanmadan önce type casting yapmamız, yani tipini vermemiz gerekiyordu. 


Örneğin eskiden şu şekilde kullanıyorduk :
1
2
3
 if (object instanceof JobImpl) { 
     return helper(((JobImpl) object).getAbstractJobType()); 
 }

Bu özellik sayesinde artık aşağıdaki şekilde kullanabiliriz :
1
2
3
 if (object instanceof JobImpl j) { 
     return helper(j.getAbstractJobType()); 
 }

Değişkenin tanımlı olduğu uzayı'da unutmamak gerekiyor.
1
2
3
4
5
 if (obj instanceof String s) { 
     // can use s here 
 } else { 
     // can't use s here 
 }

böylece daha temiz ve anlaşılır bir kod yazma imkânımız olacak. Bu özelliği denemek amaçlı yazılmış örneği buradan inceleyebilirsiniz. Preview özellikleri çalıştırabilmek için java ve javac için parametre verilmesi gerekiyor. Nasıl yapıldığını merak ediyorsanız build.xml’e bakabilirsiniz.

JEP 358: Helpful NullPointerExceptions [Ref]

Not : Bu maddeye kadar AdoptOpenJDK-OpenJ9 ile test yapıyordum ama maalesef 12.04.2020 itibarı ile maalesef bug çıktı, bundan sonrasında HotSpot ile devam edeceğim.

Yoğun nesne ve sınıf kullanımları sırasında en can sıkıcı işlerden biri de, bir şekilde oluşan NPE - NullPointerException mesajlarının kaynağını, neyin aslında Null olduğunu bulmaya çalışmaktır. Kodu debug edip bulmaya çalışırsınız, eğer ki bir de sürekli değil de arada bir karşınıza çıkıyorsa debelenip durursunuz.

Tabi eğer siz geliştirici iseniz.

Maalesef çoğu NPE'lere runtime sırasında ve/veya canlı sistemlerde oluştuğundan bu mesajları da genelde destekden sorumlu kişiler log dosyalarında görmekte bu da sorunu tespit ve çözüm sürecini daha da karmaşık hale getirmektedir. Zira hatanın oluştuğu koşulları tekrar bir araya getirip sorunu anlamak çok da kolay olmayabilir.

Görünen o ki, artık bundan sonra NPE mesajları daha anlamlı ve faydalı olacak ve bize neyin aslında Null olduğunu da söyleyecek.

Bu arada SAP'nin ticari JVM ürünü bu özelliği 2006 yılınıdan beridir içeriyormuş.

Şimdi çok rastlanılan NPE örneklerini yeni ve eski halini karşılaştırarak gözden geçirelim.


Örnek 1:

1
 a.i = 99;

Burada NPE oluştuğunda gelen mesaj şu şekilde olacak :


 Exception in thread "main" java.lang.NullPointerException at Prog.main(Prog.java:5)


Bu örnek için geliştirici a null olduğu için hata mesajı verildiğini anlamakta zorlanmayacaktır. Biraz zorlaştıralım.

Örnek 2:

1
 a.b.c.i = 99;


Burada neyin Null olduğu belli değil ve hangi dosyada ve satırda bu hatanın alındığı bilgisi mesajda olsa da hangi değişkenin null olduğu konusunda hiç bir fikir vermeyebilir. Ancak debug edip bulabilirsiniz.

Aynı durum da aşğaıdaki örnekler için de geçerlidir.

Örnek 3:

1
 a[i][j][k] = 99;


Acaba hangi dizi elemanı null ?

Örnek 4:

1
 a.i = b.j;


Sağ taraf mı sol taraf mı ?

Örnek 5:

1
 x().y().i = 99;


Hangi fonksiyon ?

Ya da gerçek hayattan bir örnek verelim :

Örnek 6:

1
 Calendar maxBaseDate = jobQueue.get(dependencyArray[0].getJsId()).getAbstractJobType().getManagement().getTimeManagement().getJsRecordedTime().getStopTime();


Burada NPE hatası alındığında nereden olduğunu bulmak için ciddi emek gerektiği aşikâr. Şimdi sırası aşağıdaki örnekleri Java14 NPE ile çalıştırıp sonuçlara bakalım.

Örnek 7:

1
a.toString().length();

1
2
3
4
 Exception in thread "main" java.lang.NullPointerException: 
    Cannot invoke "java.lang.Integer.toString()" because "a" is null
    at com.likya.java14.FeaturesJEP358.main(FeaturesJEP358.java:12)
 Java Result: 1


Örnek 8:

1
a.toString().getBytes().clone().toString();

 Exception in thread "main" java.lang.NullPointerException: 
    Cannot invoke "java.lang.Integer.toString()" because "a" is null
    at com.likya.java14.FeaturesJEP358.main(FeaturesJEP358.java:16)
 Java Result: 1


Örnek 9:

1
 b[0][0][0].length();

 Exception in thread "main" java.lang.NullPointerException: 
    Cannot load from object array because "b[0]" is null
    at com.likya.java14.FeaturesJEP358.main(FeaturesJEP358.java:23)
 Java Result: 1


Örnek 10:

1
 boolean c = a.intValue() > b.intValue();

 Exception in thread "main" java.lang.NullPointerException: 
    Cannot invoke "java.lang.Integer.intValue()" because "b" is null
    at com.likya.java14.FeaturesJEP358.main(FeaturesJEP358.java:30)
 Java Result: 1 


Örnek 11:

1
String testResult = test1().toString() + ":" + test().toString();

 Exception in thread "main" java.lang.NullPointerException: 
    Cannot invoke "java.lang.Integer.toString()" because the 
    return value of "com.likya.java14.FeaturesJEP358.test()" is null
    at com.likya.java14.FeaturesJEP358.main(FeaturesJEP358.java:32)
 Java Result: 1



Örnekleri içeren Java koduna buradan erişebilirsiniz.

Çalıştırmak için :

 ant runjpe358
Bu kadar detaylı log yazılması bazı sakıncaları da beraberinde getirmektedir örneğin performans ve risk gibi. Detaylarını merak ediyorsanız altbaşlıkta bağlantısı verilen referans dokümana bakabilirsiniz.


JEP 359: Records (Preview) [Ref]

Bu özellikle amacı sadece değiştirilmeyecek veri taşımak olan class'ların daha kolay ve basit bir tanımını yapmak mümkün olacak. Scala'da var olan case class türü bir yapı olan record, gereksiz ve sürekli kendini tekrar eden kodlama yükünden bizleri bu tür ihtiyaçların olduğu zamanalarda kurtaracak gibi.

Record, enum gibi kısıtlı bir class türü. Record isim va parametre listesinden oluşur, gövde ise opsiyoneldir.


1
 record Point(int x, int y) { }


record tanımı yaptığınızda aşağıdaki metodlar otomatik olarak gelecektir.
  • her bir argüman için private final alanı
  • her bir argüman için aynı isimde okuma amaçlı bir metod
  • tanımla aynı yapıda public contructor
  • equal and hashCode metodları
  • argüman ve class ismini gösteren bir toString metodu

Örnek 1:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
 record Cube(int x, int y, int z) {};

 public static void main(String[] args) {
    record mytestclass = new Cube(1, 2, 3);
  
    System.out.println(mytestclass.x());
    
    System.out.println(mytestclass.y());

    System.out.println(mytestclass.z());

    System.out.println(mytestclass.toString());
 }

 1
 2
 3
 Cube[x=1, y=2, z=3]


Bazı durumlarda bu class'ların tanımlarını yaparken değişiklikler yapmak da mümkün. Aşağıdaki gibi.

Örnek 2:

1
2
3
4
5
6
7
8
record Range(int lo, int hi) {
    public Range {
       if (lo > hi)  /* referring here to the implicit constructor parameters */
          throw new IllegalArgumentException(String.format("(%d,%d)", lo, hi));
    }
 }

 record rangeTest = new Range(5, 4);

 Exception in thread "main" java.lang.IllegalArgumentException: (5,4)
     at com.likya.java14.FeaturesJEP359$Range.<init>(FeaturesJEP359.java:10)
     at com.likya.java14.FeaturesJEP359.main(FeaturesJEP359.java:24)
 Cube[x=1, y=2, z=3]
 Java Result: 1



Örnekleri içeren Java koduna buradan erişebilirsiniz.

Çalıştırmak için :


 ant runjpe359
Kullanım sırasında bazı kısıtlar ve uyarılar da mevcut. Detaylı incelemek isterseniz altbaşlık referans dökümanı inceleyebilirsiniz.




Comments

Popular posts from this blog

Automation of daily build process with TlosLite

Java Sürümleri ve Özellikleri Kılavuzu