Java多行字符串

时间:2009-05-18 16:28:47

标签: java string multiline

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

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

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

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

编辑:两个答案说StringBuilder.append()优于加号表示法。任何人都可以详细说明他们为什么这么认为?它看起来并不比我更好。我正在寻找一种方法,即多行字符串不是一流的语言构造,这意味着我绝对不希望用方法调用替换第一类语言构造(字符串连接加上)。

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

43 个答案:

答案 0 :(得分:441)

听起来你想要做一个多线文字,这在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";

Versus 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();

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

Versus 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.getProperty("line.separator"),或者在%n中使用String.format

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

答案 1 :(得分:185)

在Eclipse中,如果打开选项“粘贴到字符串文字时转义文本”(在“首选项”&gt;“Java&gt;编辑器”>“打字”中),并在引号中粘贴多行字符串,它将自动添加{{所有行都有1}}和"

\n" +

答案 2 :(得分:112)

Stephen Colebourne创建了一个proposal,用于在Java 7中添加多行字符串。

此外,Groovy已经支持multi-line strings

答案 3 :(得分:93)

这是一个旧线程,但是一个新的非常优雅的解决方案(只有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. 无法将String变量定义为局部变量检查Raw String Literals project,您可以将变量定义为局部变量
  3. 该字符串不能包含Visual Basic .Net中的其他变量 使用XML文字(<%= variable %>): - )
  4. 字符串文字由JavaDoc注释(/ **)
  5. 分隔

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

    有人可能会觉得这很奇怪(Javadoc的评论并不是为了嵌入除注释之外的其他东西),但由于Java中缺少多行字符串最终会让人烦恼,我发现这是最差的解决方案。

答案 4 :(得分:58)

另一个选项可能是将长字符串存储在外部文件中,并将该文件读入字符串。

答案 5 :(得分:53)

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

示例:

    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();
}

答案 6 :(得分:44)

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

答案 7 :(得分:19)

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

string:text\u000atext\u000atext\u000a

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

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

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

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

答案 8 :(得分: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";

也就是说,在多行中打破字符串文字并没有任何惩罚,加号表示可读性。

答案 9 :(得分:13)

这是一个非常常见的问题,所以我决定将这个答案变成an article as well

Java 13及更高版本

Java现在通过Text Blocks支持多行字符串。在Java 13和14中,此功能要求您在构建和运行项目时设置––enable–preview选项。查看this Java documentation了解更多详细信息。

现在,在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文本块,您可以按以下方式重写此查询:

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 Text Blocks support

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中具有此功能,而现在我们终于有了它。

答案 10 :(得分:13)

在IntelliJ IDE中,您只需输入:

""

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

答案 11 :(得分: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);

答案 12 :(得分:10)

可悲的是,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();
}

答案 13 :(得分: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

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

根据需要修改此项以处理任何特殊情况,但这符合我的需要。希望这有帮助!

答案 14 :(得分: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

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

答案 15 :(得分:9)

JEP 326: Raw String Literals将实现多行字符串,因此您可以编写如下内容:

String s = `
    text
    text
    text
  `;

答案 16 :(得分:8)

您可以使用单独的方法连接附加内容,例如:

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

无论哪种方式,更喜欢StringBuilder加号表示法。

答案 17 :(得分:7)

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

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

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

此解决方案位于以下网址... http://www.adrianwalker.org/2011/12/java-multiline-string.html

希望有所帮助!

答案 18 :(得分:7)

Java Stringfier。如果需要,将文本转换为StringBuilder java块转义。

答案 19 :(得分:6)

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

答案 20 :(得分: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()方法的事实也未提及。

答案 21 :(得分:5)

如果您像我一样喜欢谷歌的番石榴,那么它可以提供相当干净的表示,也是一种不用硬编码换行符的简单方法:

String out = Joiner.on(newline).join(ImmutableList.of(
    "line1",
    "line2",
    "line3"));

答案 22 :(得分: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的字符串。

答案 23 :(得分:4)

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

答案 24 :(得分:3)

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

  1. 构建'文本文件到java代码'实用程序&amp;检查版本控制
  2. 在每个构建中,针对资源文件运行该实用程序以创建修订的Java源
  3. Java源代码包含一个标题 class TextBlock {...后跟一个静态字符串,该字符串是从资源文件
  4. 自动生成的
  5. 使用其余代码构建生成的java文件

答案 25 :(得分:3)

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

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

答案 26 :(得分:3)

一个不错的选择。

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);
        }

    }

答案 27 :(得分:3)

  

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

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

答案 28 :(得分:3)

通过http://schemas.android.com/apk/res-auto,现在可以按照以下方式在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...

答案 29 :(得分:2)

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

StringBuilder唯一有效的时候是使用多个语句来构造String。

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
  

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

尽可能简单明了。

答案 30 :(得分: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之神。

答案 31 :(得分:2)

这可能看起来有点疯狂,但由于heredocs是单行声明的语法糖,并且有线路传输逃脱,因此可以为Java文件编写预处理器,以便在预处理期间将heredocs更改为单行。

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

从意识形态的角度来看,它与f.g.完全不同。 “仿制药”,这也是一种预处理的语法糖,而不是铸造。

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

答案 32 :(得分:2)

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

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();

}

答案 33 :(得分: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。只需保持强力打字的做法,就可以将其取消。

答案 34 :(得分:1)

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

答案 35 :(得分:1)

使用该库

http://example.xyz.com/detail/12

可以写这样的东西

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

非常好和容易,但是仅适用于单元测试

答案 36 :(得分:1)

Java 13预览:

  

Text Blocks Come to Java. Java 13 delivers long-awaited multiline string by Mala Gupta

     

有了文本块,Java 13使您更轻松地使用多行字符串文字。您不再需要对字符串文字中的特殊字符进行转义,也不必对跨越多行的值使用串联运算符。

     

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

示例:

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

答案 37 :(得分:1)

此问题的两个答案:

  1. 如果您要坚持使用纯Java,并在2020年3月发布Java 14,则可以在第二预览模式下使用JEP 368-文本块。实际上,在其他版本中,该功能处于预览模式(至少有13个功能具有此功能)。我创建了示例集here
  2. 尽管此功能很有用,但可以容易滥用。请记住,Java需要编译-代码中包含大型字符数组可以让您轻松自如(如果需要快速更改,则需要重新编译-该工具集可能不适用于操作应用程序的人员) 。

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

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

答案 38 :(得分:1)

Java15现在在Python中支持三引号字符串。

答案 39 :(得分:0)

我对阅读多线语法确实已经计划用于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)

答案 40 :(得分:0)

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

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

答案 41 :(得分:-1)

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

下面是使用StringTemplate的简单代码示例。可以从外部纯文本文件加载实际模板(“Hello,&lt; name&gt;”)。将保留模板中的所有缩进,并且不需要转义。

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());
    }
}

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

答案 42 :(得分:-1)

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