JAVA和Nginx 教程大全

网站首页 > 精选教程 正文

Java修炼终极指南:08. 使用变量/表达式格式化文本块

wys521 2024-10-28 19:50:47 精选教程 205 ℃ 0 评论

8. 使用变量/表达式格式化文本块

在Java中,使用变量/表达式格式化字符串字面量以获取动态字符串是一种常见的做法。例如,我们可以通过众所周知的连接符“+”来创建一个动态的JSON字符串片段,如下所示:

String fn = "Jo";  
String ln = "Kym";  
String str = "<user><firstName>" + fn   
  + "</firstName><lastName>" + ln + "</lastName></user>";  
// 输出  
<user><firstName>Jo</firstName><lastName>Kym</lastName></user>


当然,从可读性的角度来看,这个简单的构造存在严重的问题。如果JSON代码按照格式和缩进进行格式化,那么它就是人类可读的,否则真的很难跟踪其层次结构。那么,我们能否将这段JSON表示为如下图的格式呢?



图1.6 - 格式化的JSON

当然可以!通过使用一些转义序列(例如,\n、\t、\s),空格等,我们可以构造一个看起来像图1.6的字符串。但是,通过文本块来表示这种连接会更好。也许我们可以在IDE的代码编辑器和IDE的控制台(在运行时)中获得相同的可读性。一种可能的方法如下所示:

String json = """  
             <user>  
                <firstName>\  
             """  
         + fn  
         + """  
              </firstName>  
                 <lastName>\  
              """  
         + ln  
         + """  
              </lastName>  
              </user>  
              """;


所以,我们可以通过"+"运算符将文本块与字符串字面量一样进行连接。酷!这段代码的输出对应于图1.6的左侧。另一方面,图1.6的右侧可以通过以下方式实现:

String json = """  
             <user>  
                <firstName>  
             """  
         + fn.indent(4) // 注意这里indent方法不是JDK自带的,可能是自定义的  
         + """  
                 </firstName>  
                 <lastName>  
              """  
         + ln.indent(4)  
         + """  
                 </lastName>  
              </user>  
              """;


虽然结果字符串在这两种情况下看起来都很好,但我们不能对代码本身说同样的话。它的可读性仍然很低。

通过查看前两个代码片段,我们可以很容易地总结出文本块的一个最佳实践:仅当文本块显著有助于代码的清晰性和多行字符串的可读性时才使用它们。另外,避免在复杂表达式(例如,在lambda表达式中)中声明文本块,因为它们可能会影响整个表达式的可读性。最好将文本块单独提取到静态变量中,并在复杂表达式中引用它们。

让我们尝试另一种方法。这次,让我们使用StringBuilder来获取图1.6左侧的结果:

StringBuilder sbJson = new StringBuilder();  
sbJson.append("""  
             <user>  
                <firstName>""")  
        .append(fn)  
        .append("""  
                </firstName>  
                   <lastName>""")  
        .append(ln)  
        .append("""  
             </lastName>  
             </user>""");


获取图1.6右侧的结果可以这样做:

StringBuilder sbJson = new StringBuilder();  
sbJson.append("""  
             <user>  
                <firstName>  
              """)  
        .append(fn.indent(4))  
        .append("""  
                </firstName>  
                <lastName>  
             """)  
        .append(ln.indent(4))  
        .append("""  
                </lastName>  
             </user>  
             """);


所以,我们可以在StringBuilder/StringBuffer中使用文本块,就像我们使用字符串字面量一样。虽然结果字符串对应于图1.6中的示例,但代码本身从可读性的角度来看仍然不尽如人意。

让我们再通过JDK 1.4的MessageFormat.format()来尝试一下。首先,让我们根据图1.6左侧的例子来格式化:

String json = MessageFormat.format("""  
                            <user>  
                                <firstName>{0}</firstName>  
                                <lastName>{1}</lastName>  
                             </user>  
                             """, fn, ln);


获取图1.6右侧的结果可以这样做:

String json = MessageFormat.format("""  
                            <user>  
                                <firstName>  
                                 {0}  
                                </firstName>  
                                <lastName>  
                                 {1}  
                                </lastName>  
                            </user>  
                            """, fn, ln);


文本块和MessageFormat.format()的组合是一个成功的做法。代码可读性显然更好。但是,让我们更进一步,并在JDK 5的String.format()中尝试一下。和往常一样,我们先展示图1.6左侧的例子:

String json = String.format("""  
                           <user>  
                               <firstName>%s</firstName>  
                               <lastName>%s</lastName>  
                           </user>  
                           """, fn, ln);


获取图1.6右侧的结果可以这样做:

String json = """  
             <user>  
                 <firstName>  
                  %s  
                 </firstName>  
                 <lastName>  
                  %s  
                 </lastName>  
             </user>  
             """.formatted(fn, ln);


文本块和String.format()的组合是另一种成功的做法,但并不是我们可以利用的最新特性。从JDK 15开始,String.format()有一个更方便的伴侣名为formatted()。以下是使用String.formatted()来复制图1.6左侧的例子:

String json = """  
             <user>  
                 <firstName>%s</firstName>  
                 <lastName>%s</lastName>  
             </user>  
             """.formatted(fn, ln);


获取图1.6右侧的结果可以这样做:

String json = """  
             <user>  
                 <firstName>  
                  %s  
                 </firstName>  
                 <lastName>  
                  %s  
                 </lastName>  
             </user>  
             """.formatted(fn, ln);


好吧,我们能做的最好的就是这样了。我们设法在IDE的代码编辑器和包含动态部分(变量)的文本块的运行时达到了相同的可读性水平。很酷,不是吗?从性能的角度来看,你可以在捆绑的代码中找到这些方法的基准测试。在下图中,你可以看到在配备Windows 10的Intel(R) Core(TM) i7-3612QM CPU @ 2.10GHz机器上的基准测试结果,但请随意在不同的机器上进行测试,因为结果高度依赖于机器。



图1.7 - 基准测试结果

根据这些结果,通过"+"运算符的连接是最快的,而MessageFormat.format()是最慢的。

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表