Java 14'de neler var - 3



JEP 368: Text Blocks (Second Preview)[Ref]

Yıllardır yazdığımız kodlar içine birden fazla satırdan olaşan text-metin eklemek istediğimizde çektiğimiz sıkınıtıyı ancak bizler gibi yaşayan bilir.

Artık bu eziyet son bulacak gibi görünüyor. Böylece string içinde kullandığımız bazı özel karakterleri escape yapmaktan kurtuluyoruz hem de istediğimiz format – biçimde birden fazla satırdan oluşan bir metni kodumuzun içerisine rahatlıkla gömebiliyoruz.

Text blok (two-dimensional) olarak tanımlanan bu yeni tip, sıfır veya daha fazla karaketerden oluşabilir.

Başlangıç ayracı """  ı takip eden sıfır veya daha fazla boşluk karakteri ve arkasından bir adet satır sonu karakteri olacak şekilde tanımlanmış. Bitiş ayracı ise """ olacak şekilde tanımlanmış. İçerik bir sonraki satırın başından itbaren başlar.

Eski tür kullanım ise one-dimensional olarak tanımlanıyor ve “ (bir adet çift tırnak) ile başlayıp bitiyordu.

Blok içeriğinde " karakteri bulunabildiği gibi \" de kulanılabilir ama gerekli değildir ve önerilmez. Ayrıca satır sonları blok içinde doğal olarak kullanılabilir ya da \n de önerilmese de kullanılabilir.

Özetle aşağıdaki ifadeler aynı sonucu üretmektedir.


1
2
3
4
5
 """
 line 1
 line 2
 line 3
 """

1
 "line 1\nline 2\nline 3\n"

1
2
3
 "line 1\n" +
 "line 2\n" +
 "line 3\n"

Eğer blok sonunda satır sonu gerekmiyorsa, bitiş ayracı son blok sonunda da bulunabilir :

1
2
3
4
 """
 line 1
 line 2
 line 3"""

Text bloğun içi boş olabilir ama önerilmez çünkü tanım için iki satır gereklidir.

1
2
 String empty = """
                """;

Bir de hatalı kullanımlara bakalım :

1
2
3
4
5
6
7
 String a = """""";   // başlangıç ayracı sonrası alt satıra geçmemiş
 String b = """ """;  // başlangıç ayracı sonrası alt satıra geçmemiş
 String c = """
            ";        // kapanış ayracı konulmamış (text bloğu dosya sonunda biter)
 String d = """
            abc \ def
            """;      // backslash karakteri escape yapılmamış (daha sonra detaylı anlatılacak)

Çokca rastlanılan örneklerden html, sql ve javascript için örnekler aşağıda. Bugüne kadar html içeriği olan bir metni eklemek için yapmamız gereken kodlama şöyle bir şey idi (one-dimensional):

1
2
3
4
5
6
7
 String html = "<html>\n" +
         "    <body>\n" +
   "        <p>Hello, world</p>\n" +
  "    </body>\n" +
  "</html>\n";

 System.out.println(html);

artık bu şekilde kullanabiliyoruz (two-dimensional ):

1
2
3
4
5
6
7
8
9
 String html = """
         <html>
     <body>
        <p>Hello, world</p>
      </body>
  </html>
  """;
 
 System.out.println(html);


     [java] <html>
     [java]     <body>
     [java]         <p>Hello, world</p>
     [java]     </body>
     [java] </html>

     [java] <html>
     [java]     <body>
     [java]         <p>Hello, world</p>
     [java]     </body>
     [java] </html>


1
2
3
4
5
 String query = "SELECT `EMP_ID`, `LAST_NAME` FROM `EMPLOYEE_TB`\n" +
  "WHERE `CITY` = 'INDIANAPOLIS'\n" +
  "ORDER BY `EMP_ID`, `LAST_NAME`;\n";
  
 System.out.println(query);


1
2
3
4
5
6
 String query = """
  SELECT `EMP_ID`, `LAST_NAME` FROM `EMPLOYEE_TB`
  WHERE `CITY` = 'INDIANAPOLIS'
  ORDER BY `EMP_ID`, `LAST_NAME`;
  """;
 System.out.println(query);


     [java] SELECT `EMP_ID`, `LAST_NAME` FROM `EMPLOYEE_TB`
     [java] WHERE `CITY` = 'INDIANAPOLIS'
     [java] ORDER BY `EMP_ID`, `LAST_NAME`;

     [java] SELECT `EMP_ID`, `LAST_NAME` FROM `EMPLOYEE_TB`
     [java] WHERE `CITY` = 'INDIANAPOLIS'
     [java] ORDER BY `EMP_ID`, `LAST_NAME`;


1
2
3
4
5
 obj = engine.eval("function hello() {\n" +
     "    print('\"Hello, world\"');\n" +
     "}\n" +
     "\n" +
     "hello();\n");


1
2
3
4
5
6
7
 obj = engine.eval("""
     function hello() {
        print('"Hello, world"');
     }
                           
     hello();
     """);


     [java] "Hello, world"

     [java] "Hello, world"


Yeni Escape Karakterler

Yeni eklenen bu string tipi ile birlikte iki yeni escape karakteri ile de tanışmamız gerekiyor. Birincisi \<satır sonu> karakteri. Bu karakteri blok içinde kullandığınız zaman artık string içinde değil ama kod içinde alt satıra geçip devam edebilirsiniz. Örneğin çok uzun string satırlarını okunabilir kılmak için alt satıra geçip yazmaya devam ettiğimiz zamanda olduğu gibi.


1
2
3
 String literal = "Lorem ipsum dolor sit amet, consectetur adipiscing " +
                  "elit, sed do eiusmod tempor incididunt ut labore " +
                  "et dolore magna aliqua.";

Eğer text bloğu kullanıyorsak şöyle olacak :


1
2
3
4
5
 String text = """
                 Lorem ipsum dolor sit amet, consectetur adipiscing \
                 elit, sed do eiusmod tempor incididunt ut labore \
                 et dolore magna aliqua.\
                 """;


 [java] literal => Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

 [java] text => Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

tabi bu escape karakter sadece text bloklarda geçerli ama eski tip string tanımlarında kullanılamaz.

İkinci karakterimiz ise \s karakteri ki tek bir boşluk karakterine karşılık gelmektedir. Escape karakterler, strip işlemi yapılıp bitene kadar derleyici tarafından işlenmezler. Bu nedenle boşluk karakterleri sonrasına eklenen \s bir nevi strip işlemine karşı kendinden önceki boşlukları koruma görevi yapacaktır.

Mesela aşağıdaki satır sonlarındaki \s karakteri kendinden önceki boşluklar için strip işlemini engelleyerek her satırın 6 karakter boyunda olmasını garanti edecektir :


1
2
3
4
5
 String colors = """
     red  \s
     green\s
     blue \s
     """;

\s karakteri hem test bloklarında hem de geleneksel string tanımlarında kullanılabilir.

Text Blokları Birbirine Ekleme İşlemi

Text blokları string kullanılan her yerde kullanılabildiği gibi birbirilerine de eklenebilirler.

1
2
3
4
5
 String code = "public void print(Object o) {" +
               """
                   System.out.println(Objects.toString(o));
               }
               """;


Fakat bazı durumlarda bu kullanım çok şık sonuçlar üretmeyebilir.

Mesela;

1
2
3
4
5
 String code = """
               public void print(Object o) {
                   System.out.println(Objects.toString(o));
               }
               """;


Diyelim ki fonksiyonun parameteresi bir başka değişkenden gelecek ve dinamik olacak. Bu durumda araya değişken eklersek, """ sonrası satır başı yapmamız zorunlu olduğundan ve görsel biçimi de bozmak istemediğimizden "type" ve "o" arasına bir sürü gereksiz boşluk doldurmak zorunda kalacağız.

1
2
3
4
5
6
 String code = """
               public void print(""" + type + """
                                                  o) {
                   System.out.println(Objects.toString(o));
               }
               """;


Oysa ki elimizde seçeneklerimiz var. Örneğin String::replace veya String::format kullanmak.

1
2
3
4
5
 String code = """
               public void print($type o) {
                   System.out.println(Objects.toString(o));
               }
               """.replace("$type", type);


1
2
3
4
5
 String code = String.format("""
               public void print(%s o) {
                   System.out.println(Objects.toString(o));
               }
               """, type);


Diğer bir seçenek ise yeni eklenen String::formatted metodunu kullanmak.

1
2
3
4
5
 String source = """
                 public void print(%s object) {
                     System.out.println(Objects.toString(object));
                 }
                 """.formatted(type);


     [java] public void print(Array o) {
     [java]     System.out.println(Objects.toString(o));
     [java] }

     [java] public void print(Array o) {
     [java]     System.out.println(Objects.toString(o));
     [java] }

     [java] public void print(Array object) {
     [java]     System.out.println(Objects.toString(object));
     [java] }


Yeni Gelen Metodlar

Text Blokları desteklemek amaçlı aşağıdaki metodlar eklenmiş
  • String::stripIndent(): text blok içindeki boşlukarı temizler.
  • String::translateEscapes():text blok içindeki escape karakterleri dönüştürür
  • String::formatted(Object... args): string içindeki değişkenleri argüman listesi ile değiştirir.


Bu metodlardan üçüncüyü zaten yukarıda kullandık. Diğer ikisinin nasıl çalıştığını anlamak için de aşağıda görebilirsiniz.


1
2
3
4
 data = readFileAsString();
 System.out.println(data);
 System.out.println(data.stripIndent());
 System.out.println(data.stripIndent().translateEscapes());


     [java]                                                                     <html>
     [java]                                                                             <body>
     [java]                                                                                     <p>Hello, world</p>
     [java]                                                                                     Merhaba \\n\\nBen \\"geldim\\"
     [java]                                                                             </body>
     [java]                                                                     </html>
     
     [java] <html>
     [java]     <body>
     [java]             <p>Hello, world</p>
     [java]             Merhaba \\n\\nBen \\"geldim\\"
     [java]     </body>
     [java] </html>
     
     [java] <html>
     [java]     <body>
     [java]             <p>Hello, world</p>
     [java]             Merhaba
     [java]
     [java] Ben "geldim"
     [java]     </body>
     [java] </html>

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

Çalıştırmak için :


ant runjep368

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