• JDK13中将增加文本块特性


    摘要

    JDK13中将加入文本块功能。

    本篇文章将有以下内容:

    1. 新版JDK中加入文本块的动机是什么?
    2. 文本块如何使用
    3. 文本块的编译
    4. 文本块的连接

    目标

    • 简化跨越多行的字符串,避免对换行等特殊字符进行转义,简化编写Java程序。
    • 增强Java程序中字符串的可读性。

    动机

    在Java中,通常需要使用String类型表达HTML,XML,SQL或JSON等格式的字符串,在进行字符串赋值时需要进行转义和连接操作,然后才能编译该代码,这种表达方式难以阅读并且难以维护。

    无论文本是来自其他编程语言的代码,还是自然语言,在Java程序中表示短文本,中文本和长文本需要有通用的表达方式。

    因此,文本块将提高Java程序的可读性和可写性。

    HTML example

    没有文本块时:

    String html = "<html>
    " +
                  "    <body>
    " +
                  "        <p>Hello, world</p>
    " +
                  "    </body>
    " +
                  "</html>
    ";

    使用文本块后

    String html = """
                  <html>
                      <body>
                          <p>Hello, world</p>
                      </body>
                  </html>
                  """;

    SQL example

    没有文本块时:

    String query = "SELECT `EMP_ID`, `LAST_NAME` FROM `EMPLOYEE_TB`
    " +
                   "WHERE `CITY` = 'INDIANAPOLIS'
    " +
                   "ORDER BY `EMP_ID`, `LAST_NAME`;
    ";

    使用文本块后

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

    描述

    文本块是Java语言中的一种新文字。它可以用来表示任何字符串,并且提供更大的表现力和更少的复杂性。

    文本块由零个或多个字符组成,由开始和结束分隔符括起来。

    开始分隔符是由三个双引号字符("""),后面可以跟零个或多个空格,最终以行终止符结束。文本块内容以开始分隔符的行终止符后的第一个字符开始。

    结束分隔符也是由三个双引号字符表示,文本块内容以结束分隔符的第一个双引号之前的最后一个字符结束。

    文本块中的内容可以直接使用","可以使用,但不是必需的。

    文本块中的内容可以直接包括行终止符。允许在文本块中使用 n,但不是必需的。例如,文本块:

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

    相当于:

    "line 1
    line 2
    line 3
    "

    或者一个连接的字符串:

    "line 1
    " +
    "line 2
    " +
    "line 3
    "

    如果字符串末尾不需要行终止符,则结束分隔符可以放在最后一行内容上。例如:

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

    相当于:

    "line 1
    line 2
    line 3"

    文本块可以表示空字符串,但不建议这样做,因为它需要两行源代码:

    String empty = """
    """;

    以下示例是错误格式的文本块:

    String a = """""";   // 开始分隔符后没有行终止符
    String b = """ """;  // 开始分隔符后没有行终止符
    String c = """
               ";        // 没有结束分隔符
    String d = """
               abc  def
               """;      // 含有未转义的反斜线(请参阅下面的转义处理)

    编译处理

    文本块是String类型的常量表达式,就像字符串一样。

    但是,与字符串不同,Java编译器分为三个步骤来处理文本块的内容:

    1. 内容中的行终止符被转换为LF( u000A)。此转换的目的是在跨平台移动Java源代码时遵循最小惊喜原则
    2. 为了匹配Java源代码的缩进,将内容中的多余的空格删除。
    3. 解释内容中的转义字符。这作为最后一步意味着开发人员可以编写转义字符,例如 ,而不会被之前的步骤修改或删除。

    最小惊喜原则:总是做最不令人意外的事情

    处理后的内容作为常量池中的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>
                      <body>
                          <p>Hello, world</p>
                      </body>
                  </html>
                  """;

    请注意,在文本块内自由使用"是合法的,即使在开始或结束分隔符旁边也是如此。例如:

    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);

    参考:https://openjdk.java.net/jeps/355

    总结

    本文写在JDK13还未正式发布之前,也是希望能让大家先睹为快,同时希望JDK13能尽快发布,让我们Javer能用上更方便的语言。

  • 相关阅读:
    CAS 5.X 安装
    《从0到1》开启商业和未来的秘密
    阿里Java开发规约插件使用
    【Effective Java】阅读
    Java8 流的使用示例
    我对线程安全的理解
    APP微信支付实现
    如何将微信上传AMR格式语音转化为MP3格式
    如何在下载文件前确定文件名
    寻找水王1
  • 原文地址:https://www.cnblogs.com/lanqingzhou/p/13590459.html
Copyright © 2020-2023  润新知