在Java中,文本块是多行字符串文字。这意味着我们不需要陷入显式的行终止符,字符串连接以及分隔符的混乱局面,而这些分隔符通常用于编写普通的字符串文字。

Java文本块在Java13中可用(JEP355)和Java14(JEP368)作为预览函数。它计划成为Java15的标准函数(JEP378)。

java13之前多行文本的写法

package com.morris.java17;

/**
 * java13之前json字符串的写法
 */
public class TextBlockBefore13Demo {
    public static void main(String[] args) {
        String json = "{\n"
                + "  \"name\": \"morris\",\n"
                + "  \"age\": \"18\"\n"
                + "}";
        // 为了看到效果,将空格替换为.
        json = json.replaceAll("\s", ".");
        System.out.println(json);
    }
}

运行结果如下:

{
.."name":."morris",
.."age":."18"
}

文本块语法

文本块包含多行文本,并使用三个双引号字符(“”")作为其开始和结束定界符。

开头的三个双引号字符后总是一个行终止符。内容只能从下一行开始。

结尾的三个双引号字符可以和前面的内容在一行上。

如果文本内容包含单引号或双引号,则无需将其转义。

package com.morris.java17;

/**
 * java13文本
 */
public class TextBlock13Demo {
    public static void main(String[] args) {
        String json = """
         {
           "name": "morris",
           "age": "18"
         }
         """;
        // 为了看到效果,将空格替换为.
        json = json.replaceAll("\s", ".");
        System.out.println(json);
    }
}

运行结果如下:

{
.."name":."morris",
.."age":."18"
}

类似字符串

从文本块生成的实例的类型为java.lang.String,其特征与传统的双引号字符串相同。这包括对象表示和插入字符串池。
我们可以使用文本块作为String类型的方法参数传递。

package com.morris.java17;

/**
 * 文本框与字符串的比较
 */
public class TextBlockAndStringCompareDemo {
    public static void main(String[] args) {
        String s1 = "hello";
        String s2 = """
                hello""";
        System.out.println(s1 == s2); // true
    }
}

文本块可以在可以使用字符串文字的任何地方使用。例如,我们可以将其用于字符串连接。

文本块字符串具有与字符串相同的方法,如contains()、indexOf()和length()函数。

文本块缩进

自动去除后面的缩进

下面例子中文本块的每行后面都有两个空格,但是输出结果显示每行后面没有空格了,说明文本块会自动去除后面的缩进。

package com.morris.java17;

/**
 * 文本块中的缩进,自动去除后面的缩进
 */
public class TextBlockIndentDemo {
    public static void main(String[] args) {
        // 每行后面都有两个空格
        String t1 = """
         {  
           "name": "morris",    
           "age": "18"  
         }
         """;
        // 为了看到效果,将空格替换为.
        t1 = t1.replaceAll("\s", ".");
        System.out.println(t1);
    }
}

运行结果如下:

{
.."name":."morris",
.."age":."18"
}

自动保留前面的缩进

下面的例子中,将结尾的三个双引号"""放在文本块中每行的开始位置前一位,这样就会文本块自动保留前面的缩进。

package com.morris.java17;

/**
 * 文本块中的缩进,自动保留前面的缩进
 */
public class TextBlockIndentDemo2 {
    public static void main(String[] args) {
        // 每行前面保留一个空格
        String t2 = """
         {
           "name": "morris",
           "age": "18"
         }
        """;
        // 为了看到效果,将空格替换为.
        t2 = t2.replaceAll("\s", ".");
        System.out.println(t2);
    }
}

运行结果如下:

.{
..."name":."morris",
..."age":."18"
.}

手动保留后面的缩进

如果由于某种原因我们不希望删除缩进,可以使用\s(ASCII字符32,空格)转义序列。在任何行的末尾使用它可以保证该行将具有所有空格字符,直到遇到\s

package com.morris.java17;

/**
 * 文本块中的缩进,手动保留后面的缩进
 */
public class TextBlockIndentDemo3 {
    public static void main(String[] args) {
        // 每行前面保留一个空格
        String t2 = """
        {    \s
          "name": "morris",    \s
          "age": "18"    \s
        }    \s
        """;
        // 为了看到效果,将空格替换为.
        t2 = t2.replaceAll("\s", ".");
        System.out.println(t2);
    }
}

运行结果如下:

{.....
.."name":."morris",.....
.."age":."18".....
}.....

转义序列

很多时候,我们只想将内容写到程序的多行中,但实际上它们在运行的时候只是一行字符串内容。在这种情况下,我们可以使用换行符换码符,即单个反斜杠\。它禁止包含隐式换行符。

package com.morris.java17;

/**
 * java14文本块使用\表示禁止包含隐式换行符
 */
public class TextBlockEscapeDemo {
    public static void main(String[] args) {
        String json = """
         {\
         "name": "bob", "age": "32"\
         }\
         """;
        System.out.println(json);
    }
}

运行结果如下:

{"name": "bob", "age": "32"}