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

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

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

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

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

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


当前回答

这是一个老线程,但是一个新的非常优雅的解决方案(只有4个或3个小缺点)是使用自定义注释。

查询:http://www.adrianwalker.org/2011/12/java-multiline-string.html

受此启发的一个项目托管在GitHub上:

https://github.com/benelog/multiline

Java代码示例:

import org.adrianwalker.multilinestring.Multiline;
...
public final class MultilineStringUsage {

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

  public static void main(final String[] args) {
    System.out.println(html);
  }
}

缺点是

您必须激活相应的(提供的)注释 处理器。 该字符串变量不能定义为局部变量检查原始字符串字面量项目,其中您可以将变量定义为局部变量 字符串不能像在Visual Basic .Net中那样包含其他变量 使用XML文本(<%=变量%>):-) 字符串文字由JavaDoc注释(/**)分隔

而且您可能必须配置Eclipse/Intellij-Idea,使其不会自动重新格式化Javadoc注释。

有人可能会觉得这很奇怪(Javadoc注释并不是为嵌入注释以外的任何内容而设计的),但由于Java中缺少多行字符串确实令人讨厌,因此我认为这是最不糟糕的解决方案。

其他回答

这是你不应该在不考虑它在做什么的情况下使用的东西。但对于一次性脚本,我已经成功地使用了这个方法:

例子:

    System.out.println(S(/*
This is a CRAZY " ' ' " multiline string with all sorts of strange 
   characters!
*/));

代码:

// From: http://blog.efftinge.de/2008/10/multi-line-string-literals-in-java.html
// Takes a comment (/**/) and turns everything inside the comment to a string that is returned from S()
public static String S() {
    StackTraceElement element = new RuntimeException().getStackTrace()[1];
    String name = element.getClassName().replace('.', '/') + ".java";
    StringBuilder sb = new StringBuilder();
    String line = null;
    InputStream in = classLoader.getResourceAsStream(name);
    String s = convertStreamToString(in, element.getLineNumber());
    return s.substring(s.indexOf("/*")+2, s.indexOf("*/"));
}

// From http://www.kodejava.org/examples/266.html
private static String convertStreamToString(InputStream is, int lineNum) {
    /*
     * To convert the InputStream to String we use the BufferedReader.readLine()
     * method. We iterate until the BufferedReader return null which means
     * there's no more data to read. Each line will appended to a StringBuilder
     * and returned as String.
     */
    BufferedReader reader = new BufferedReader(new InputStreamReader(is));
    StringBuilder sb = new StringBuilder();

    String line = null; int i = 1;
    try {
        while ((line = reader.readLine()) != null) {
            if (i++ >= lineNum) {
                sb.append(line + "\n");
            }
        }
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        try {
            is.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    return sb.toString();
}

JEP 378: Text Blocks涵盖了此功能,并且包含在JDK 15中。它最初出现在JDK 13中的JEP 355: Text Blocks(预览)和JDK 14中的JEP 368: Text Blocks(第二预览),可以在这些版本中通过——enable-preview javac选项启用。

语法允许这样写:

String s = """
           text
           text
           text
           """;

在此之前,在JDK 12中,JEP 326: Raw String Literals旨在实现类似的功能,但最终被撤回:

请注意:这原本是JDK 12中的预览语言功能,但它已被撤回,并没有出现在JDK 12中。它在JDK 13中被文本块(JEP 355)所取代。

另一种方法是将长字符串存储在外部文件中,然后将文件读入字符串。

如果你在属性文件中定义字符串,它看起来会更糟糕。IIRC,它看起来像:

string:text\u000atext\u000atext\u000a

一般来说,在源代码中不嵌入大字符串是一个合理的想法。您可能希望将它们作为资源加载,可能以XML或可读的文本格式加载。文本文件可以在运行时读取,也可以编译成Java源代码。如果你最终把它们放在源代码中,我建议把+放在前面,省略不必要的新行:

final String text = ""
    +"text "
    +"text "
    +"text"
;

如果你有新的行,你可能需要一些join或格式化方法:

final String text = join("\r\n"
    ,"text"
    ,"text"
    ,"text"
);

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