来自Perl,我肯定错过了在源代码中创建多行字符串的“here-document”方法:

$string = <<"EOF"  # create a three-line string
text
text
text
EOF

在Java中,当我从头开始连接多行字符串时,我必须在每一行上使用繁琐的引号和加号。

有什么更好的选择吗?在属性文件中定义我的字符串?

编辑:有两个答案说StringBuilder.append()比加号更可取。谁能详细解释一下他们为什么这么想?在我看来,这一点也不可取。我正在寻找一种方法来解决多行字符串不是一级语言结构这一事实,这意味着我绝对不想用方法调用取代一级语言结构(字符串连接与加号)。

编辑:为了进一步澄清我的问题,我根本不关心性能。我关心的是可维护性和设计问题。


当前回答

一个非常高效且与平台无关的解决方案是使用系统属性的行分隔符和StringBuilder类来构建字符串:

String separator = System.getProperty("line.separator");
String[] lines = {"Line 1", "Line 2" /*, ... */};

StringBuilder builder = new StringBuilder(lines[0]);
for (int i = 1; i < lines.length(); i++) {
    builder.append(separator).append(lines[i]);
}
String multiLine = builder.toString();

其他回答

我所知道的唯一方法是用加号连接多行

String.join

Java 8为Java .lang. string添加了一个新的静态方法,它提供了一个更好的选择:

String.join ( CharSequence分隔符, CharSequence进行…元素 )

使用它:

String s = String.join(
    System.getProperty("line.separator"),
    "First line.",
    "Second line.",
    "The rest.",
    "And the last!"
);

Java 13预览:

Text Blocks Come to Java. Java 13 delivers long-awaited multiline string by Mala Gupta With text blocks, Java 13 is making it easier for you to work with multiline string literals. You no longer need to escape the special characters in string literals or use concatenation operators for values that span multiple lines. Text block is defined using three double quotes (""") as the opening and closing delimiters. The opening delimiter can be followed by zero or more white spaces and a line terminator.

例子:

 String s1 = """
 text
 text
 text
 """;

Java 13及以上版本

Java中现在通过文本块支持多行字符串。在Java 13和14中,这个特性要求你在构建和运行项目时设置——enable-preview选项。在Java 15及以后版本中,由于文本块已成为标准特性,因此不再需要此选项。查看官方的文本块编程指南,了解更多细节。

现在,在Java 13之前,你是这样写查询的:

List<Tuple> posts = entityManager
.createNativeQuery(
    "SELECT *\n" +
    "FROM (\n" +
    "    SELECT *,\n" +
    "           dense_rank() OVER (\n" +
    "               ORDER BY \"p.created_on\", \"p.id\"\n" +
    "           ) rank\n" +
    "    FROM (\n" +
    "        SELECT p.id AS \"p.id\",\n" +
    "               p.created_on AS \"p.created_on\",\n" +
    "               p.title AS \"p.title\",\n" +
    "               pc.id as \"pc.id\",\n" +
    "               pc.created_on AS \"pc.created_on\",\n" +
    "               pc.review AS \"pc.review\",\n" +
    "               pc.post_id AS \"pc.post_id\"\n" +
    "        FROM post p\n" +
    "        LEFT JOIN post_comment pc ON p.id = pc.post_id\n" +
    "        WHERE p.title LIKE :titlePattern\n" +
    "        ORDER BY p.created_on\n" +
    "    ) p_pc\n" +
    ") p_pc_r\n" +
    "WHERE p_pc_r.rank <= :rank\n",
    Tuple.class)
.setParameter("titlePattern", "High-Performance Java Persistence %")
.setParameter("rank", 5)
.getResultList();

多亏了Java 13 Text Blocks,你可以像下面这样重写这个查询:

List<Tuple> posts = entityManager
.createNativeQuery("""
    SELECT *
    FROM (
        SELECT *,
               dense_rank() OVER (
                   ORDER BY "p.created_on", "p.id"
               ) rank
        FROM (
            SELECT p.id AS "p.id",
                   p.created_on AS "p.created_on",
                   p.title AS "p.title",
                   pc.id as "pc.id",
                   pc.created_on AS "pc.created_on",
                   pc.review AS "pc.review",
                   pc.post_id AS "pc.post_id"
            FROM post p
            LEFT JOIN post_comment pc ON p.id = pc.post_id
            WHERE p.title LIKE :titlePattern
            ORDER BY p.created_on
        ) p_pc
    ) p_pc_r
    WHERE p_pc_r.rank <= :rank
    """,
    Tuple.class)
.setParameter("titlePattern", "High-Performance Java Persistence %")
.setParameter("rank", 5)
.getResultList();

可读性强多了,对吧?

支持的想法

IntelliJ IDEA提供了将传统字符串连接块转换为新的多行字符串格式的支持:

Json, html, XML

多行String在编写JSON、HTML或XML时特别有用。

考虑下面的例子,使用String连接来构建一个JSON字符串文字:

entityManager.persist(
    new Book()
    .setId(1L)
    .setIsbn("978-9730228236")
    .setProperties(
        "{" +
        "   \"title\": \"High-Performance Java Persistence\"," +
        "   \"author\": \"Vlad Mihalcea\"," +
        "   \"publisher\": \"Amazon\"," +
        "   \"price\": 44.99," +
        "   \"reviews\": [" +
        "       {" +
        "           \"reviewer\": \"Cristiano\", " +
        "           \"review\": \"Excellent book to understand Java Persistence\", " +
        "           \"date\": \"2017-11-14\", " +
        "           \"rating\": 5" +
        "       }," +
        "       {" +
        "           \"reviewer\": \"T.W\", " +
        "           \"review\": \"The best JPA ORM book out there\", " +
        "           \"date\": \"2019-01-27\", " +
        "           \"rating\": 5" +
        "       }," +
        "       {" +
        "           \"reviewer\": \"Shaikh\", " +
        "           \"review\": \"The most informative book\", " +
        "           \"date\": \"2016-12-24\", " +
        "           \"rating\": 4" +
        "       }" +
        "   ]" +
        "}"
    )
);

由于转义字符和大量的双引号和加号,您几乎无法阅读JSON。

使用Java文本块,JSON对象可以这样写:

entityManager.persist(
    new Book()
    .setId(1L)
    .setIsbn("978-9730228236")
    .setProperties("""
        {
           "title": "High-Performance Java Persistence",
           "author": "Vlad Mihalcea",
           "publisher": "Amazon",
           "price": 44.99,
           "reviews": [
               {
                   "reviewer": "Cristiano",
                   "review": "Excellent book to understand Java Persistence",
                   "date": "2017-11-14",
                   "rating": 5
               },
               {
                   "reviewer": "T.W",
                   "review": "The best JPA ORM book out there",
                   "date": "2019-01-27",
                   "rating": 5
               },
               {
                   "reviewer": "Shaikh",
                   "review": "The most informative book",
                   "date": "2016-12-24",
                   "rating": 4
               }
           ]
        }
        """
    )
);

自从我在2004年使用c#以来,我一直希望在Java中有这个功能,现在我们终于有了它。

实际上,下面是我迄今为止见过的最干净的实现。它使用注释将注释转换为字符串变量…

/**
  <html>
    <head/>
    <body>
      <p>
        Hello<br/>
        Multiline<br/>
        World<br/>
      </p>
    </body>
  </html>
  */
  @Multiline
  private static String html;

因此,最终结果是变量html包含多行字符串。没有引号,没有加号,没有逗号,只有纯字符串。

该解决方案可在以下URL… http://www.adrianwalker.org/2011/12/java-multiline-string.html

希望有帮助!