JDK13中将加入 文本块 功能。 本篇文章将有以下内容:
在Java中,通常需要使用String类型表达HTML,XML,SQL或JSON等格式的字符串,在进行字符串赋值时需要进行转义和连接操作,然后才能编译该代码,这种表达方式难以阅读并且难以维护。
无论文本是来自其他编程语言的代码,还是自然语言,在Java程序中表示短文本,中文本和长文本需要有通用的表达方式。
因此, 文本块 将提高Java程序的可读性和可写性。
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> """; 复制代码
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语言中的一种新文字。它可以用来表示任何字符串,并且提供更大的表现力和更少的复杂性。
文本块由零个或多个字符组成,由开始和结束分隔符括起来。
开始分隔符是由三个双引号字符("""),后面可以跟零个或多个空格,最终以行终止符结束。文本块内容以开始分隔符的行终止符后的第一个字符开始。
结束分隔符也是由三个双引号字符表示,文本块内容以结束分隔符的第一个双引号之前的最后一个字符结束。
文本块中的内容可以直接使用","可以使用,但不是必需的。
文本块中的内容可以直接包括行终止符。允许在文本块中使用/ 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编译器分为三个步骤来处理文本块的内容:
最小惊喜原则:总是做最不令人意外的事情
处理后的内容作为常量池中的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