Java 14'de neler var - 2



JEP 361: Switch Expressions (Standard)[Ref]

Yapılan bu değişiklik ile switch ifadesi statement ya da expression olarak kullanılabilecek. İkisi arasındaki fark nedir dediğinizi duyar gibiyim. Expression, işlem bloğunun fonksiyon benzeri bir geri dönüş değeri üretmesidir. Statement ise , yaptığı işlem sonucunda bir dönüş değeri üretmez.

Burada switch bağlamında ifade edecek olur ise, belli bir blok olarak tanımlanıp bir takım işlemler yapan bir "statement" iken artık bir ifadenin parçası olarak da kullanılabilecek. Kullanım geleneksel case... : label şeklinde (fall through) ya da yeni hali ile case ... -> label (no fall through)  kullanılabilir ya da yield ile bir değer döndürebilirsiniz.

Fall through, case’ler arasında break olmadığı zaman program aşağı doğru akmasını ifade etmektedir. Bakalım neler olmuş.


Arrow Labels :

“case L :” olarak kullandığımız yapıya yine scala dakine benzer bir şekilde ek olarak “case L ->” olarak kullanım imkânı da eklenmiş. Eğer L:Label ifadesine eşit bir değer gelirse yalnızca okun sağ tarafındaki expression ya da stament çalıştırılır.

Sağ taraftaki ifade tek satırlık bir işlem olabileceği gibi {} ile tanımlanmış bir blok olabilir ya da exception da atabilir. Kod aşağı doğru akmaz blok bitince ya da satır sonunda son bulur.

Burada yeni bir durum ile karşı karşıyayız. Eğer case 'lerden birinde bir yerel değişken tanımlanmak isteniyorsa, eskisinden farklı olarak artık bir blok içinde tanımlanmalı ve böylece artık scope sadece blok ile kısıtlanmış olur. Bu da geleneksel case kullanımında can sıkıcı bir durum olan tanımlanmış değişkenin tüm case bloğu içerisinde geçerli olması durumunu ortadan kaldırır.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
     switch (day) {
        case MONDAY:
        case TUESDAY:
           int temp = 1;     // The scope of 'temp' continues to the }
           break;
        case WEDNESDAY:
        case THURSDAY:
        int temp2 = 1;    // Can't call this variable 'temp', used temp2
           break;
        default:
           int temp3 = 1;    // Can't call this variable 'temp' or 'temp2', used temp3
     }

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
 public static void brandNewSwitchStatement() {
  
    var day = days.TUESDAY;
  
    switch (day) {
       case MONDAY, FRIDAY, SUNDAY -> System.out.println(6);
       case TUESDAY                -> System.out.println(7);
       case THURSDAY, SATURDAY     -> System.out.println(8);
       case WEDNESDAY              -> System.out.println(9);
    }
  
 }

1
2
3
4
5
6
7
 static void howMany(int k) {
    switch (k) {
       case 1  -> System.out.println("one");
       case 2  -> System.out.println("two");
       default -> System.out.println("many");
    }
 }


 howMany(1);
 howMany(2);
 howMany(3);
şeklinde howMany fonksiyonu çalıştırıldığına aşağıdaki sonuçlar elde edilecektir.


 one
 two
 many


Switch Expression

Ne şekilde kullanılacağı örnekle daha net anlaşılıyor.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
 public static void switchAsExpression() {
 
    System.out.println("Running sample : switchAsExpression ");
    
    int k = 0;
  
    System.out.println(
       switch (k) {
          case  1 -> "one";
          case  2 -> "two";
          default -> "many";
       }
    );

 }


 Running sample : switchAsExpression
 many

Görüldüğü gibi switch bloğu gelen değere göre işlem yapıp sonuç üretip bunu fonksiyon gibi çağrıldığı yere döndürebiliyor.


Yielding a value

Yazılan kodlarda çoğunlukla switch case L -> sağ tarafında tek satırlık bir sonuç üretici ifade bulunması yeterli olacaktır. Eğer tek satır yerine daha karmaşık bir işlem yapma gereği ile bir işlem bloğu ihtiyacı olur ise bu durumlar için yield kelimesi kullanarak blok sonucunda bir çıktı üretebiliriz.


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
 public static void switchAsExpressionWithYield() {
 
    System.out.println("Running sample : switchAsExpressionWithYield ");
    
    var day = days.TUESDAY;
  
    int j = switch (day) {
       case MONDAY  -> 0;
       case TUESDAY -> 1;
       default      -> {
          int k = day.toString().length();
          int result = f(k);
          yield result;
       }
    };
 
    System.out.println("j : " + j);
 }


 Running sample : switchAsExpressionWithYield
 j : 1

switch expression ifadesi geleneksel tarzda “case L : ....” ve fall through anımsatacak şekilde de kullanılabilir. Bu durumda yield ile sonuç üretmek mümkün.


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
 public static void yieldWithTraditionalSwitch() {
  
    System.out.println("Running sample : yieldWithTraditionalSwitch ");

    String s = "Fuuu";
  
    int result = switch (s) {
       case "Foo": 
          yield 1;
       case "Bar":
          yield 2;
       default:
          System.out.println("Neither Foo nor Bar, hmmm...");
          yield 0;
    };
  
    System.out.println("value of result : " + result);
 }

 Running sample : yieldWithTraditionalSwitch
 Neither Foo nor Bar, hmmm...
 value of result : 0
Aslında “break” ve “yield” ifadeleri bize switch kullanımının bir statementmı yoksa expressionmı olduğunu açıkça gösterecektir. Eğer break kullanılmışsa statement, yield kullanılmışsa expression olduğunu rahatlıkla söyleyebiliriz.

Son olarak ifade etmek lazım ki, eğer switch expression olarak kullanılacak ise, ihtimallerin tümünü içermeli ya da default seçeneği eklenmeli ve bir değer dönüşü yapmalı ya da Exception atmalıdır.

Aksi taktirde kodunuz derleme hatası alacaktır.


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
 public static void exhaustiveness1() {

    System.out.println("Running sample : exhaustiveness1 ");
    var day = days.FRIDAY;
  
    int i = switch (day) {
       case MONDAY -> {
             System.out.println("Monday"); 
              // ERROR! Block doesn't contain a yield statement
          }
       default -> 1;
    };
 }

 public static void exhaustiveness2() {

    System.out.println("Running sample : exhaustiveness2 ");
    var day = days.FRIDAY;
  
    int i = switch (day) {
       case MONDAY, TUESDAY, WEDNESDAY: yield 0;
       default: 
    System.out.println("Second half of the week");
    // ERROR! Group doesn't contain a yield statement
       };
 }

 public static void exhaustiveness3() {

    System.out.println("Running sample : exhaustiveness1 ");
    var day = days.FRIDAY;
  
    int i = switch (day) {
       case MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY -> {
          yield 1;
       }
    };
 }


 [javac] D:\dev\git\java-works\Java14NewFeatures\src\com\likya\java14\FeaturesJEP361.java:145: error: switch rule completes without providing a value
 [javac]             }
 [javac]             ^
 [javac]   (switch rules in switch expressions must either provide a value or throw)
 [javac] D:\dev\git\java-works\Java14NewFeatures\src\com\likya\java14\FeaturesJEP361.java:161: error: switch expression completes without providing a value
 [javac]             };
 [javac]             ^
 [javac]   (switch expressions must either provide a value or throw for all possible input values)
 [javac] D:\dev\git\java-works\Java14NewFeatures\src\com\likya\java14\FeaturesJEP361.java:169: error: the switch expression does not cover all possible input values
 [javac]             int i = switch (day) {
 [javac]                     ^
 [javac] Note: Some input files use preview language features.
 [javac] Note: Recompile with -Xlint:preview for details.
 [javac] 3 errors

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

Çalıştırmak için :


 ant runjep361

Detaylarını merak ediyorsanız alt başlıkta bağlantısı verilen referans dokümana bakabilirsiniz.

Comments

Popular posts from this blog

Automation of daily build process with TlosLite

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

Java 14'de neler var - 1