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

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

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

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

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

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


当前回答

当我读到多行语法确实是为jdk7计划的(在java存在了多少年之后?)时,我有点恼火。有趣的是,甚至还没有readAll()函数用于读取文件的完整内容(仅从jdk7读取,啊啊),因此下面的代码读取单行。

/*
  MakeMultiline v1.0 (2010) - Free to use and copy.

  Small gadget to turn text blobs into one java string literal
  (doing the split in lines, adding \n at each end and enclosing
  in double quotes). Does escape quotes encountered in the text blob.

  Useful for working around missing multiline string syntax in java
  prior jdk7. Use with:

     java MakeMultiline "    "
  or
     java MakeMultiline "    " mytextfile.txt
*/

import java.io.*;

class MakeMultiline {
  public static void main(String[] args) {
    try {
      // args[0]: indent
      // args[1]: filename to read (optional; stdin if not given)
      // Beware the nmb of newlines at the end when using stdin!

      String indent = (args.length > 0 ? args[0] : "");
      FileReader fr = null; BufferedReader br;
      if (args.length > 1)
        { fr =  new FileReader(args[1]); br = new BufferedReader(fr); }
      else
        { br = new BufferedReader(new InputStreamReader(System.in)); }
      String s; String res = "";
      while((s = br.readLine()) != null) {
        if (res.length() > 0) res += " +\n";
        res += indent + "\"" + s.replace("\"", "\\\"") + "\\n\"";
      }
      br.close(); if (fr != null) fr.close();
      System.out.println(res + ";");
    }
    catch(Exception e) {
      System.out.println("Exception: " + e);
    }
  }
}

这对我来说是最快的解决办法。(2010-01-27)

其他回答

后期模型JAVA对+和常量字符串进行了优化,在幕后使用了StringBuffer,所以你不想让它使你的代码变得混乱。

它指出了JAVA的一个疏忽,它不像ANSI C在双引号字符串之间只有空白的自动连接,例如:

const char usage = "\n"
"Usage: xxxx <options>\n"
"\n"
"Removes your options as designated by the required parameter <options>,\n"
"which must be one of the following strings:\n"
"  love\n"
"  sex\n"
"  drugs\n"
"  rockandroll\n"
"\n" ;

我想有一个多行字符数组常量,其中嵌入换行是光荣的,所以我可以在没有任何混乱的情况下呈现块,例如:

String Query = "
SELECT
    some_column,
    another column
  FROM
      one_table a
    JOIN
      another_table b
    ON    a.id = b.id
      AND a.role_code = b.role_code
  WHERE a.dept = 'sales'
    AND b.sales_quote > 1000
  Order BY 1, 2
" ;

要做到这一点,需要打败JAVA之神。

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

遗憾的是,Java没有多行字符串字面量。您要么必须连接字符串字面量(使用+或StringBuilder是最常见的两种方法),要么从单独的文件中读取字符串。

对于大的多行字符串文字,我倾向于使用一个单独的文件,并使用getResourceAsStream() (Class类的一个方法)读取它。这使得查找文件变得很容易,因为您不必担心当前目录与代码安装的位置。它还使打包更容易,因为您实际上可以将文件存储在jar文件中。

假设你在一个名为Foo的类中。就像这样做:

Reader r = new InputStreamReader(Foo.class.getResourceAsStream("filename"), "UTF-8");
String s = Utils.readAll(r);

另一个烦恼是Java没有标准的“将这个Reader中的所有文本读入字符串”方法。写起来很简单:

public static String readAll(Reader input) {
    StringBuilder sb = new StringBuilder();
    char[] buffer = new char[4096];
    int charsRead;
    while ((charsRead = input.read(buffer)) >= 0) {
        sb.append(buffer, 0, charsRead);
    }
    input.close();
    return sb.toString();
}

一个非常高效且与平台无关的解决方案是使用系统属性的行分隔符和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();

看到所有的答案,我认为没有人提到比在java的新版本,你可以这样做:

String s = """
    This
    is 
    a
    multiline
    string
    """;
System.out.println(s);

这是它打印的内容:

This
is
a
multiline
string