JDK13中將增長文本塊特性

摘要

JDK13中將加入文本塊功能。 本篇文章將有如下內容:html

  1. 新版JDK中加入文本塊的動機是什麼?
  2. 文本塊如何使用
  3. 文本塊的編譯
  4. 文本塊的鏈接

目標

  • 簡化跨越多行的字符串,避免對換行等特殊字符進行轉義,簡化編寫Java程序。
  • 加強Java程序中字符串的可讀性。

動機

在Java中,一般須要使用String類型表達HTML,XML,SQL或JSON等格式的字符串,在進行字符串賦值時須要進行轉義和鏈接操做,而後才能編譯該代碼,這種表達方式難以閱讀而且難以維護。java

不管文本是來自其餘編程語言的代碼,仍是天然語言,在Java程序中表示短文本,中文本和長文本須要有通用的表達方式。程序員

所以,文本塊將提升Java程序的可讀性和可寫性。編程

HTML example

沒有文本塊時:bash

String html = "<html>\n" +
              " <body>\n" +
              " <p>Hello, world</p>\n" +
              " </body>\n" +
              "</html>\n";
複製代碼

使用文本塊後微信

String html = """
              <html>
                  <body>
                      <p>Hello, world</p>
                  </body>
              </html>
              """;
複製代碼

SQL example

沒有文本塊時:less

String query = "SELECT `EMP_ID`, `LAST_NAME` FROM `EMPLOYEE_TB`\n" +
               "WHERE `CITY` = 'INDIANAPOLIS'\n" +
               "ORDER BY `EMP_ID`, `LAST_NAME`;\n";
複製代碼

使用文本塊後編程語言

String query = """
               SELECT `EMP_ID`, `LAST_NAME` FROM `EMPLOYEE_TB`
               WHERE `CITY` = 'INDIANAPOLIS'
               ORDER BY `EMP_ID`, `LAST_NAME`;
               """;
複製代碼

描述

文本塊是Java語言中的一種新文字。它能夠用來表示任何字符串,而且提供更大的表現力和更少的複雜性。ide

文本塊由零個或多個字符組成,由開始和結束分隔符括起來。學習

開始分隔符是由三個雙引號字符("""),後面能夠跟零個或多個空格,最終以行終止符結束。文本塊內容以開始分隔符的行終止符後的第一個字符開始。

結束分隔符也是由三個雙引號字符表示,文本塊內容以結束分隔符的第一個雙引號以前的最後一個字符結束。

文本塊中的內容能夠直接使用","可使用,但不是必需的。

文本塊中的內容能夠直接包括行終止符。容許在文本塊中使用\ n,但不是必需的。例如,文本塊:

""" line 1 line 2 line 3 """
複製代碼

至關於:

"line 1\nline 2\nline 3\n"
複製代碼

或者一個鏈接的字符串:

"line 1\n" +
"line 2\n" +
"line 3\n"
複製代碼

若是字符串末尾不須要行終止符,則結束分隔符能夠放在最後一行內容上。例如:

""" line 1 line 2 line 3"""
複製代碼

至關於:

"line 1\nline 2\nline 3"
複製代碼

文本塊能夠表示空字符串,但不建議這樣作,由於它須要兩行源代碼:

String empty = """ """;
複製代碼

如下示例是錯誤格式的文本塊:

String a = """""";   // 開始分隔符後沒有行終止符
String b = """ """;  // 開始分隔符後沒有行終止符
String c = """ ";        // 沒有結束分隔符
String d = """ abc \ def """;      // 含有未轉義的反斜線(請參閱下面的轉義處理)
複製代碼

編譯處理

文本塊是String類型的常量表達式,就像字符串同樣。 可是,與字符串不一樣,Java編譯器分爲三個步驟來處理文本塊的內容:

  1. 內容中的行終止符被轉換爲LF(\ u000A)。此轉換的目的是在跨平臺移動Java源代碼時遵循最小驚喜原則
  2. 爲了匹配Java源代碼的縮進,將內容中的多餘的空格刪除。
  3. 解釋內容中的轉義字符。這做爲最後一步意味着開發人員能夠編寫轉義字符,例如\n,而不會被以前的步驟修改或刪除。

最小驚喜原則:老是作最不使人意外的事情

處理後的內容做爲常量池中的CONSTANT_String_info條目記錄在類文件中,就像字符串同樣。

在運行時,文本塊將被實例化爲String的實例,就像字符串同樣。從文本塊派生的String實例與從字符串派生的實例是沒法區分的。具備相同內容的兩個文本塊將引用相同的String實例,就像字符串同樣。

如下部分將更詳細地討論了編譯時的處理。

行終止符

文本塊內容中的行終止符由Java編譯器把CR(\ u000D)和CRLF(\ u000D \ u000A)標準化爲LF(\ u000A)。這樣確保了文本塊內容在不一樣平臺上是等效的。

多餘的空格

下面這段代碼中,咱們用.來表示咱們代碼中的的空格,而這些位置的空格就是多餘的。

String html = """
..............<html>
..............    <body>
..............        <p>Hello, world</p>
..............    </body>
..............</html>
..............""";
複製代碼

多餘的空格還會出如今每一行的結尾,特別是當你從其餘地方複製過來時,更容易出現這種狀況,好比下面的代碼:

String html = """
..............<html>...
..............    <body>
..............        <p>Hello, world</p>....
..............    </body>.
..............</html>...
..............""";
複製代碼

這些多餘的空格對於程序員來講是看不到的,可是他又是實際存在的,因此若是編譯器不作處理,可能會致使程序員看到的兩個文本塊內容是同樣的,可是這兩個文本塊卻由於存在這種多餘的空格而致使差別,好比哈希值不相等。

因此編譯器在編譯時會刪除掉這些多餘的空格。

轉義字符

容許開發人員使用\ n,\ f和\ r來進行字符串的垂直格式化,使用\ b和\ t進行水平格式化。好比下面的代碼是合法的:

String html = """
              <html>\r
                  <body>\r
                      <p>Hello, world</p>\r
                  </body>\r
              </html>\r
              """;
複製代碼

請注意,在文本塊內自由使用"是合法的,即便在開始或結束分隔符旁邊也是如此。例如:

String story = """
    "When I use a word," Humpty Dumpty said,
    in rather a scornful tone, "it means just what I
    choose it to mean - neither more nor less."
    "The question is," said Alice, "whether you
    can make words mean so many different things."
    "The question is," said Humpty Dumpty,
    "which is to be master - that's all."""";
複製代碼

可是,三個"字符的序列須要進行轉義至少一個"以免模仿結束分隔符:

String code = 
    """
    String text = \"""
        A text block inside a text block
    \""";
    """;
複製代碼

文本塊鏈接

能夠在任何可使用字符串的地方使用文本塊。例如,文本塊和字符串能夠相互鏈接:

String code = "public void print(Object o) {" +
              """
                  System.out.println(Objects.toString(o));
              }
              """;
複製代碼

可是,涉及文本塊的鏈接可能變得至關笨重。如下面文本塊爲基礎:

String code = """
              public void print(Object o) {
                  System.out.println(Objects.toString(o));
              }
              """;
複製代碼

假設咱們想把上面的Object改成來至某一變量,咱們可能會這麼寫:

String code = """
              public void print(""" + type + """
               o) {
                  System.out.println(Objects.toString(o));
              }
              """;
複製代碼

能夠發現這種寫法可讀性是很是差的,更簡潔的替代方法是使用String :: replace或String :: format,好比:

String code = """
              public void print($type o) {
                  System.out.println(Objects.toString(o));
              }
              """.replace("$type", type);
複製代碼
String code = String.format("""
              public void print(%s o) {
                  System.out.println(Objects.toString(o));
              }
              """, type);
複製代碼

另外一個方法是使用String :: formatted,這是一個新方法,好比:

String source = """
                public void print(%s object) {
                    System.out.println(Objects.toString(object));
                }
                """.formatted(type);
複製代碼

參考:openjdk.java.net/jeps/355

總結

本文寫在JDK13還未正式發佈以前,也是但願能讓你們先睹爲快,同時但願JDK13能儘快發佈,讓咱們Javer能用上更方便的語言。 若是以爲這篇文章能讓你學到知識,可否幫忙轉發,將知識分享出去。 若是想第一時間學習更多的精彩的內容,請關注微信公衆號:1點25

相關文章
相關標籤/搜索