571

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

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

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

有哪些更好的选择?在属性文件中定义我的字符串?

编辑:两个答案说 StringBuilder.append() 比加号更可取。谁能详细说明他们为什么这么认为?它看起来一点也不适合我。我正在寻找一种解决方法,即多行字符串不是一流的语言构造,这意味着我绝对不想用方法调用替换一流的语言构造(字符串连接加号)。

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

4

44 回答 44

535

注意:此答案适用于 Java 14 及更早版本。

Java 15 中引入了文本块(多行文字)。有关详细信息,请参阅此答案


听起来你想做一个多行文字,这在 Java 中不存在。

您最好的选择是将字符串+组合在一起。人们提到的其他一些选项(StringBuilder、String.format、String.join)只有在您从字符串数组开始时才会更可取。

考虑一下:

String s = "It was the best of times, it was the worst of times,\n"
         + "it was the age of wisdom, it was the age of foolishness,\n"
         + "it was the epoch of belief, it was the epoch of incredulity,\n"
         + "it was the season of Light, it was the season of Darkness,\n"
         + "it was the spring of hope, it was the winter of despair,\n"
         + "we had everything before us, we had nothing before us";

对战StringBuilder

String s = new StringBuilder()
           .append("It was the best of times, it was the worst of times,\n")
           .append("it was the age of wisdom, it was the age of foolishness,\n")
           .append("it was the epoch of belief, it was the epoch of incredulity,\n")
           .append("it was the season of Light, it was the season of Darkness,\n")
           .append("it was the spring of hope, it was the winter of despair,\n")
           .append("we had everything before us, we had nothing before us")
           .toString();

对战String.format()

String s = String.format("%s\n%s\n%s\n%s\n%s\n%s"
         , "It was the best of times, it was the worst of times,"
         , "it was the age of wisdom, it was the age of foolishness,"
         , "it was the epoch of belief, it was the epoch of incredulity,"
         , "it was the season of Light, it was the season of Darkness,"
         , "it was the spring of hope, it was the winter of despair,"
         , "we had everything before us, we had nothing before us"
);

与 Java8 相比String.join()

String s = String.join("\n"
         , "It was the best of times, it was the worst of times,"
         , "it was the age of wisdom, it was the age of foolishness,"
         , "it was the epoch of belief, it was the epoch of incredulity,"
         , "it was the season of Light, it was the season of Darkness,"
         , "it was the spring of hope, it was the winter of despair,"
         , "we had everything before us, we had nothing before us"
);

如果您想要特定系统的换行符,您需要使用System.lineSeparator(),或者您可以使用%nin String.format

另一种选择是将资源放在文本文件中,然后读取该文件的内容。这对于非常大的字符串会更可取,以避免不必要地膨胀您的类文件。

于 2009-05-18T16:57:04.967 回答
193

在 Eclipse 中,如果您打开选项“粘贴到字符串文字时转义文本”(在 Preferences > Java > Editor > Typing 中)并将多行字符串粘贴到引号中,它将自动为您的所有行添加"\n" +

String str = "paste your text here";
于 2011-10-10T17:07:02.957 回答
123

Stephen Colebourne提出了在 Java 7 中添加多行字符串的提议。

此外,Groovy 已经支持多行字符串

于 2009-05-18T17:47:24.820 回答
102

这是一个旧线程,但一个新的非常优雅的解决方案(只有 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);
  }
}

缺点是

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

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

有人可能会觉得这很奇怪(Javadoc 注释并非旨在嵌入除注释之外的任何内容),但由于 Java 中缺少多行字符串最终真的很烦人,我发现这是最不糟糕的解决方案。

于 2012-08-01T07:46:34.133 回答
75

JEP 378: Text Blocks涵盖了此功能,并包含在 JDK 15 中。它最初以JEP 355: Text Blocks (Preview) in JDK 13 和JEP 368: Text Blocks (Second Preview)在 JDK 14 中出现,并且可以在这些版本中启用使用––enable–previewjavac 选项。

语法允许编写如下内容:

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

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

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

于 2018-05-03T12:31:36.603 回答
65

另一种选择可能是将长字符串存储在外部文件中并将文件读入字符串。

于 2009-05-18T16:38:29.530 回答
60

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

例子:

    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();
}
于 2009-11-03T15:55:30.027 回答
59

String.join

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

String.join( CharSequence delimiter , CharSequence... elements )

使用它:

String s = String.join(
    System.getProperty("line.separator"),
    "First line.",
    "Second line.",
    "The rest.",
    "And the last!"
);
于 2014-07-17T12:12:02.807 回答
34

Java 13 及更高版本

Java 现在通过Text Blocks支持多行字符串。在 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();

更具可读性,对吧?

IDE 支持

IntelliJ IDEA 支持将传统String连接块转换为新的多行String格式:

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 中拥有这个功能,现在我们终于有了。

于 2020-03-06T08:59:16.657 回答
19

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

string:text\u000atext\u000atext\u000a

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

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

如果您确实有新行,您可能需要一些连接或格式化方法:

final String text = join("\r\n"
    ,"text"
    ,"text"
    ,"text"
);
于 2009-05-18T16:47:43.300 回答
17

加号被转换为 StringBuilder.append,除非两个字符串都是常量,因此编译器可以在编译时将它们组合起来。至少,Sun 的编译器是这样的,我怀疑大多数(如果不是所有)其他编译器都会这样做。

所以:

String a="Hello";
String b="Goodbye";
String c=a+b;

通常会生成与以下内容完全相同的代码:

String a="Hello";
String b="Goodbye":
StringBuilder temp=new StringBuilder();
temp.append(a).append(b);
String c=temp.toString();

另一方面:

String c="Hello"+"Goodbye";

是相同的:

String c="HelloGoodbye";

也就是说,为了便于阅读,在多行中使用加号打破字符串文字不会受到任何惩罚。

于 2009-05-19T00:37:21.683 回答
17

在 IntelliJ IDE 中,您只需键入:

""

然后将光标放在引号内并粘贴您的字符串。IDE 会将其扩展为多个连接的行。

于 2016-10-08T16:28:13.033 回答
11

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

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

假设你在一个名为 Foo 的类中。只需执行以下操作:

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

另一个烦恼是Java没有标准的“从这个阅读器中读取所有文本到字符串中”的方法。不过写起来很容易:

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();
}
于 2009-05-18T17:10:10.307 回答
10
String newline = System.getProperty ("line.separator");
string1 + newline + string2 + newline + string3

但是,最好的选择是使用String.format

String multilineString = String.format("%s\n%s\n%s\n",line1,line2,line3);
于 2009-05-18T16:34:34.590 回答
9

您可以使用与 java 兼容的 scala-code,并允许使用 """ 括起来的多行字符串:

package foobar
object SWrap {
  def bar = """John said: "This is
  a test
  a bloody test,
  my dear." and closed the door.""" 
}

(注意字符串内的引号)和来自java:

String s2 = foobar.SWrap.bar ();

这是否更舒服......?

如果您经常处理应该放在源代码中的长文本,另一种方法可能是脚本,它从外部文件中获取文本,并将其包装为 multiline-java-String ,如下所示:

sed '1s/^/String s = \"/;2,$s/^/\t+ "/;2,$s/$/"/' file > file.java

这样您就可以轻松地将其剪切并粘贴到您的源代码中。

于 2010-05-18T05:27:08.727 回答
9

由于 Java 不(还)本机支持多行字符串,因此目前唯一的方法是使用上述技术之一绕过它。我使用上面提到的一些技巧构建了以下 Python 脚本:

import sys
import string
import os

print 'new String('
for line in sys.stdin:
    one = string.replace(line, '"', '\\"').rstrip(os.linesep)
    print '  + "' + one + ' "'
print ')'

将其放入名为 javastringify.py 的文件中,并将您的字符串放入 mystring.txt 文件中,然后按如下方式运行它:

cat mystring.txt | python javastringify.py

然后,您可以复制输出并将其粘贴到您的编辑器中。

根据需要修改它以处理任何特殊情况,但这适合我的需要。希望这可以帮助!

于 2011-02-21T18:22:12.263 回答
7

您可以在单独的方法中连接您的追加,例如:

public static String multilineString(String... lines){
   StringBuilder sb = new StringBuilder();
   for(String s : lines){
     sb.append(s);
     sb.append ('\n');
   }
   return sb.toString();
}

无论哪种方式,都更喜欢StringBuilder加号。

于 2009-05-18T16:40:53.143 回答
7

请参阅Java Stringfier。如果需要,将您的文本转换为 StringBuilder java 块转义。

于 2012-01-13T21:52:01.157 回答
7
    import org.apache.commons.lang3.StringUtils;

    String multiline = StringUtils.join(new String[] {
        "It was the best of times, it was the worst of times ", 
        "it was the age of wisdom, it was the age of foolishness",
        "it was the epoch of belief, it was the epoch of incredulity",
        "it was the season of Light, it was the season of Darkness",
        "it was the spring of hope, it was the winter of despair",
        "we had everything before us, we had nothing before us",
        }, "\n");
于 2014-06-03T07:17:16.547 回答
7

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

/**
  <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

希望有帮助!

于 2014-07-14T01:32:44.633 回答
6

我还没有看到答案的另一种选择是java.io.PrintWriter.

StringWriter stringWriter = new StringWriter();
PrintWriter writer = new PrintWriter(stringWriter);
writer.println("It was the best of times, it was the worst of times");
writer.println("it was the age of wisdom, it was the age of foolishness,");
writer.println("it was the epoch of belief, it was the epoch of incredulity,");
writer.println("it was the season of Light, it was the season of Darkness,");
writer.println("it was the spring of hope, it was the winter of despair,");
writer.println("we had everything before us, we had nothing before us");
String string = stringWriter.toString();

java.io.BufferedWriter也没有提到有newLine()方法的事实。

于 2009-11-03T16:06:24.340 回答
6

Java 13 预览:

文本块来到 Java。Java 13 提供了 Mala Gupta 期待已久的多行字符串

借助文本块,Java 13 使您可以更轻松地处理多行字符串文字。您不再需要转义字符串文字中的特殊字符或对跨越多行的值使用连接运算符。

文本块使用三个双引号 (""") 作为开始和结束分隔符来定义。开始分隔符后面可以跟零个或多个空格和一个行终止符。

例子:

 String s1 = """
 text
 text
 text
 """;
于 2019-10-28T21:48:18.863 回答
5

一个非常有效且独立于平台的解决方案是使用系统属性作为行分隔符和 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();
于 2009-05-18T16:47:57.013 回答
5

使用Properties.loadFromXML(InputStream). 不需要外部库。

比凌乱的代码更好(因为您关心可维护性和设计),最好不要使用长字符串。

从读取 xml 属性开始:

 InputStream fileIS = YourClass.class.getResourceAsStream("MultiLine.xml");
 Properties prop = new Properies();
 prop.loadFromXML(fileIS);


那么您可以以更易于维护的方式使用您的多行字符串...

static final String UNIQUE_MEANINGFUL_KEY = "Super Duper UNIQUE Key";
prop.getProperty(UNIQUE_MEANINGFUL_KEY) // "\n    MEGA\n   LONG\n..."


MultiLine.xml` 位于同一文件夹 YourClass 中:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">

<properties>
    <entry key="Super Duper UNIQUE Key">
       MEGA
       LONG
       MULTILINE
    </entry>
</properties>

PS.:您可以将<![CDATA["..."]]>用于类似 xml 的字符串。

于 2014-02-15T19:53:49.990 回答
5

使用JDK/12 early access build #12,现在可以在 Java 中使用多行字符串,如下所示:

String multiLine = `First line
    Second line with indentation
Third line
and so on...`; // the formatting as desired
System.out.println(multiLine);

这将导致以下输出:

First line
    Second line with indentation
Third line
and so on...

编辑:推迟到 java 13

于 2018-09-21T09:44:06.143 回答
4

如果你和我一样喜欢 google 的 guava,它可以提供一个相当干净的表示和一个很好、简单的方法来不硬编码你的换行符:

String out = Joiner.on(newline).join(ImmutableList.of(
    "line1",
    "line2",
    "line3"));
于 2012-07-10T17:08:27.990 回答
4

一个不错的选择。

import static some.Util.*;

    public class Java {

        public static void main(String[] args) {

            String sql = $(
              "Select * from java",
              "join some on ",
              "group by"        
            );

            System.out.println(sql);
        }

    }


    public class Util {

        public static String $(String ...sql){
            return String.join(System.getProperty("line.separator"),sql);
        }

    }
于 2016-05-18T02:38:15.817 回答
3

在属性文件中定义我的字符串?

属性文件中不允许使用多行字符串。您可以在属性文件中使用 \n ,但我认为这不是您的解决方案。

于 2009-05-18T16:43:20.267 回答
3

我建议使用 ThomasP 建议的实用程序,然后将其链接到您的构建过程中。仍然存在包含文本的外部文件,但在运行时不会读取该文件。那么工作流程是:

  1. 构建一个“文本文件到 Java 代码”实用程序并检查版本控制
  2. 在每次构建时,针对资源文件运行该实用程序以创建修改后的 Java 源
  3. Java 源代码包含一个标头, class TextBlock {...后跟一个从资源文件自动生成的静态字符串
  4. 使用其余代码构建生成的 java 文件
于 2010-05-17T14:57:58.833 回答
3

我知道这是一个老问题,但是对于有兴趣的开发人员来说,多行文字将出现在 #Java12 中

http://mail.openjdk.java.net/pipermail/amber-dev/2018-July/003254.html

于 2018-07-07T22:15:30.103 回答
2

当使用一长串 + 时,只会创建一个 StringBuilder,除非在编译时确定 String,在这种情况下不使用 StringBuilder!

只有当使用多个语句来构造 String 时,StringBuilder 才更有效。

String a = "a\n";
String b = "b\n";
String c = "c\n";
String d = "d\n";

String abcd = a + b + c + d;
System.out.println(abcd);

String abcd2 = "a\n" +
        "b\n" +
        "c\n" +
        "d\n";
System.out.println(abcd2);

注意:只创建一个 StringBuilder。

  Code:
   0:   ldc     #2; //String a\n
   2:   astore_1
   3:   ldc     #3; //String b\n
   5:   astore_2
   6:   ldc     #4; //String c\n
   8:   astore_3
   9:   ldc     #5; //String d\n
   11:  astore  4
   13:  new     #6; //class java/lang/StringBuilder
   16:  dup
   17:  invokespecial   #7; //Method java/lang/StringBuilder."<init>":()V
   20:  aload_1
   21:  invokevirtual   #8; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
   24:  aload_2
   25:  invokevirtual   #8; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
   28:  aload_3
   29:  invokevirtual   #8; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
   32:  aload   4
   34:  invokevirtual   #8; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
   37:  invokevirtual   #9; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
   40:  astore  5
   42:  getstatic       #10; //Field java/lang/System.out:Ljava/io/PrintStream;
   45:  aload   5
   47:  invokevirtual   #11; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
   50:  ldc     #12; //String a\nb\nc\nd\n
   52:  astore  6
   54:  getstatic       #10; //Field java/lang/System.out:Ljava/io/PrintStream;
   57:  aload   6
   59:  invokevirtual   #11; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
   62:  return

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

让它尽可能清晰和简单。

于 2009-05-19T19:07:51.177 回答
2

一个小技巧。使用这个我在动态创建的 HTML 页面中注入 javascritp

StringBuilder builder = new StringBuilder();

public String getString()
{
    return builder.toString();
}
private DropdownContent _(String a)
{
    builder.append(a);
    return this;
}

public String funct_showhide()
{
   return
    _("function slidedown_showHide(boxId)").
    _("{").
    _("if(!slidedown_direction[boxId])slidedown_direction[boxId] = 1;").
    _("if(!slideDownInitHeight[boxId])slideDownInitHeight[boxId] = 0;").
    _("if(slideDownInitHeight[boxId]==0)slidedown_direction[boxId]=slidedownSpeed; ").
    _("else slidedown_direction[boxId] = slidedownSpeed*-1;").
    _("slidedownContentBox = document.getElementById(boxId);").
    _("var subDivs = slidedownContentBox.getElementsByTagName('DIV');").
    _("for(var no=0;no<subDivs.length;no++){").
    _(" if(subDivs[no].className=='dhtmlgoodies_content')slidedownContent = subDivs[no];").
    _("}").
    _("contentHeight = slidedownContent.offsetHeight;").
    _("slidedownContentBox.style.visibility='visible';").
    _("slidedownActive = true;").
    _("slidedown_showHide_start(slidedownContentBox,slidedownContent);").
    _("}").getString();

}
于 2010-12-12T18:39:44.153 回答
2

这可能看起来有点疯狂,但由于 heredocs 是单行声明的语法糖,换行符已转义,因此可以为 Java 文件编写预处理器,在预处理期间将 heredocs 更改为单行。

它需要在编译阶段(用于 ant/maven 构建)和 IDE 插件之前编写适当的插件来预处理文件。

从意识形态的角度来看,它与 fg “泛型”没有什么不同,后者也是一种预处理语法糖而不是强制转换。

然而,这是很多工作,所以我会在你的地方只使用 .properties 文件。

于 2012-01-14T07:40:08.070 回答
2

后期模型 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 众神。

于 2013-04-01T17:40:23.097 回答
2

Java15 现在支持像 Python 一样的三引号字符串。

于 2020-11-11T01:41:30.680 回答
1

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

于 2009-05-18T16:32:44.877 回答
1

我看到至少有一种情况应该避免对长字符串使用外部文件:如果这些长字符串是单元测试文件中的预期值,因为我认为测试应该始终以它们不使用的方式编写依赖任何外部资源。

于 2010-10-24T11:27:12.043 回答
1

我有时会使用一个并行的 groovy 类来充当一袋字符串

这里的java类

public class Test {
    public static void main(String[] args) {
        System.out.println(TestStrings.json1);
        // consume .. parse json
    }
}

以及 TestStrings.groovy 中令人垂涎的多行字符串

class TestStrings {
    public static String json1 = """
    {
        "name": "Fakeer's Json",
        "age":100,
        "messages":["msg 1","msg 2","msg 3"]
    }""";
}

当然,这仅适用于静态字符串。如果我必须在文本中插入变量,我只需将整个文件更改为 groovy。只要保持强类型的做法,它就可以被取消。

于 2014-03-17T05:37:50.073 回答
1

使用这个库

https://github.com/alessio-santacroce/multiline-string-literals

可以这样写

System.out.println(newString(/*
      Wow, we finally have
      multiline strings in
      Java! HOOO!
*/));

非常好用且简单,但仅适用于单元测试

于 2018-12-04T11:43:49.197 回答
1

这个问题的两个答案:

  1. 如果您想坚持使用纯 Java,Java 14 将于 2020 年 3 月发布,您可以在第二预览模式下利用JEP 368 - 文本块。实际上,该功能在其他版本中处于预览模式(至少有 13 个)。我在这里创建并设置了示例。
  2. 虽然此功能很有用,但很容易被滥用。请记住,Java 需要编译——在你的代码中包含大型字符数组可能是一个让你自责的简单方法(如果你想快速改变,你将需要重新编译——那个工具集可能对操作你的应用程序的人不可用) .

根据我的经验,建议在配置文件中保留大字符串(通常是应用程序操作员可以/应该在运行时更改的字符串)。

摘要:负责任地使用文本块:)。

于 2020-02-17T05:38:55.337 回答
0

一个简单的选择是使用 SciTE ( http://www.scintilla.org/SciTEDownload.html ) 之类的编辑器编辑您的 java 代码,它允许您包装文本,以便轻松查看和编辑长字符串。如果您需要转义字符,只需将它们放入。通过关闭 wrap-option,您可以检查您的字符串确实仍然只是一个长的单行字符串。但当然,如果不是,编译器也会告诉你。

Eclipse 或 NetBeans 是否支持编辑器中的文本换行,我不知道,因为它们有很多选择。但如果没有,那将是一件好事。

于 2009-08-26T20:33:23.157 回答
0

读到确实为 jdk7 计划了多行语法,我有点恼火(在 Java 存在大约几十年之后?)。有趣的是,甚至还没有用于读取文件完整内容的 readAll() 函数(仅来自 jdk7,呵呵),所以下面的代码读取单行。

/*
  MakeMultiline v1.0 (2010) - 免费使用和复制。

  将文本 blob 转换为一个 java 字符串文字的小工具
  (在行中进行拆分,在每一端添加 \n 并封闭
  双引号)。是否对文本 blob 中遇到的引号进行转义。

  对于解决 java 中缺少的多行字符串语法很有用
  之前的jdk7。用于:

     java MakeMultiline " "
  或者
     java MakeMultiline " " mytextfile.txt
*/

导入java.io.*;

类 MakeMultiline {
  公共静态无效主要(字符串[]参数){
    尝试 {
      // args[0]: 缩进
      // args[1]: 要读取的文件名(可选;如果没有给出标准输入)
      // 使用标准输入时要注意末尾换行的 nmb!

      字符串缩进 = (args.length > 0 ? args[0] : "");
      文件阅读器 fr = null; BufferedReader br;
      如果 (args.length > 1)
        { fr = new FileReader(args[1]); br = new BufferedReader(fr); }
      别的
        { br = new BufferedReader(new InputStreamReader(System.in)); }
      字符串 s; 字符串 res = "";
      while((s = br.readLine()) != null) {
        if (res.length() > 0) res += " +\n";
        res += 缩进 + "\"" + s.replace("\"", "\\\"") + "\\n\"";
      }
      br.close(); if (fr != null) fr.close();
      System.out.println(res + ";");
    }
    捕获(异常 e){
      System.out.println("异常:" + e);
    }
  }
}

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

于 2010-01-27T19:04:15.693 回答
0

如果作者有兴趣使用某种需要具有一些动态值的格式化大字符串,则问题并不完全清楚,但如果是这种情况,则使用像 StringTemplate (http://www.stringtemplate.org/)这样的模板引擎可能非常有用。

下面是一个使用 StringTemplate 的简单代码示例。可以从外部纯文本文件加载实际模板(“Hello, < name >”)。模板中的所有缩进都将被保留,无需转义。

import org.stringtemplate.v4.*;
 
public class Hello {
    public static void main(String[] args) {
        ST hello = new ST("Hello, <name>");
        hello.add("name", "World");
        System.out.println(hello.render());
    }
}

PS 出于可读性和本地化目的,从源代码中删除大块文本总是一个好主意。

于 2014-12-05T22:28:20.877 回答
-3

您可以使用 Kotlin 多行字符串支持。

只需创建一个 Kotlin 类,并在那里使用它,

您可以将 kotlin 类称为 java synxtax

//科特林

    fun jsIncreaseOrDecreaseWebFonts(webView : YHYWebView, sliderValue : Int, intFontSize : Int){
            var initialData = """
                  bla bla
                """

}

//来自Java

 KotlinFunctions t = new KotlinFunctions();
 t.jsIncreaseOrDecreaseWebFonts(webView,progresValue,incOrDec);
于 2021-12-11T09:14:38.100 回答