Triple quotes in Java like Scala

37.8k views Asked by At

In Scala you can do something like this:

val expr = """ This is a "string" with "quotes" in it! """

Is there something like this in Java? I abhor using "\"" to represent strings with quotes in them. Especially when composing key/value pairs in JSON. Disgusting!

6

There are 6 answers

4
rgettman On BEST ANSWER

Note: This answer was written prior to Java 15, which introduced the triple-quote text block feature. Please see @epox's answer for how to use this feature.


There is no good alternative to using \" to include double-quotes in your string literal.

There are bad alternatives:

  • Use \u0022, the Unicode escape for a double-quote character. The compiler treats a Unicode escape as if that character was typed. It's treated as a double-quote character in the source code, ending/beginning a String literal, so this does NOT work.
  • Concatenate the character '"', e.g. "This is a " + '"' + "string". This will work, but it seems to be even uglier and less readable than just using \".
  • Concatenate the char 34 to represent the double-quote character, e.g. "This is a " + (char) 34 + "string". This will work, but it's even less obvious that you're attempting to place a double-quote character in your string.
  • Copy and paste Word's "smart quotes", e.g. "This is a “string” with “quotes” in it!". These aren't the same characters (Unicode U+201C and U+201D); they have different appearances, but they'll work.

I suppose to hide the "disgusting"-ness, you could hide it behind a constant.

public static final String DOUBLE_QUOTE = "\"";

Then you could use:

String expr = " This is a " + DOUBLE_QUOTE + "string" + DOUBLE_QUOTE + ...;

It's more readable than other options, but it's still not very readable, and it's still ugly.

There is no """ mechanism in Java, so using the escape \", is the best option. It's the most readable, and it's the least ugly.

0
kiedysktos On

The feature of "Raw String Literals" was meant to be in Java 12, but was withdrawn due to some criticism, because they planned to use variable number of backquotes (`).

So it is in Java 13 finally, as "Text Block" feature, but in preview only. It is using """ operator like in Scala.

You can read more on Java 13 features here.

0
jumping_monkey On

The feature that you want is called Text Blocks and delivered in Java 15, JEP378.

History

Text blocks were proposed by JEP 355 in early 2019 as a follow-on to explorations begun in JEP 326 (Raw String Literals), which was initially targeted to JDK 12 but eventually withdrawn and did not appear in that release. JEP 355 was targeted to JDK 13 in June 2019 as a preview feature. Feedback on JDK 13 suggested that text blocks should be previewed again in JDK 14, with the addition of two new escape sequences. Consequently, JEP 368 was targeted to JDK 14 in November 2019 as a preview feature. Feedback on JDK 14 suggested that text blocks were ready to become final and permanent in JDK 15 with no further changes.

Usage

String query = """
               SELECT "EMP_ID", "LAST_NAME" FROM "EMPLOYEE_TB"
               WHERE "CITY" = 'INDIANAPOLIS'
               ORDER BY "EMP_ID", "LAST_NAME";
               """;
0
Paul Rambags On

The triple quote feature is available since Java 14. For more details, see for instance, https://howtodoinjava.com/java14/java-text-blocks/

4
Joris On

Found this question while doing the same thing: composing small literal JSON strings for quick testing. One alternative that didn't come up is to use double single-quotes and replace them with double quotes, something like:

String json = "{ ''label'' : ''set range'', ''min'' : 0, ''max'' : 100}".replace("''", "\"")

Obviously this doesn't work if there's a regular double single quote, but chances of that should be slim. It's not a great solution, but looks better than lots of backslashes, imo. As an intermediate step to putting the json in a separate file, this is probably not too bad.

0
epox On

Since Java 15

or since Java 13 preview feature. REF: https://openjdk.java.net/jeps/355

It doesn't work precisely in Scala way. The opening triple quotes must be followed by a new line.

var expr = """
           This is a 1-line "string" with "quotes" and no leading spaces in it! """;

The position of the closing triple quotes matters. It defines the indent size. For example, for having 2 spaces indent, you position your closing """ as follows:

String sql = """
               SELECT   emp_id, last_name
               FROM     postgres.employee
               WHERE    city = 'INDIANAPOLIS'
               ORDER BY emp_id, last_name;
             """;

this would result in 4 lines of text:

  SELECT   emp_id, last_name
  FROM     postgres.employee
  WHERE    city = 'INDIANAPOLIS'
  ORDER BY emp_id, last_name;

Escaping:

Tripple quotes escaping is intuitive:

String txt = """
    A text block with three quotes \""" inside.""";

\ (backslash) is still a special symbol. You have to escape it by doubling \\:

String txt = """
    A text block with a single blackslash \\ in it.""";

Trailing spaces

Java compiler ignores any ending spaces.

WORKAROUND: add \s to the end of the line. (Baeldung example)


Windows \r\n line terminators

No matter if you compile in MacOs or Windows, the string constant will always use \n and only \n

WORKAROUND: add \r to the end of the line. (Baeldung example)


Concatenating 2 lines

Since Java 14 preview, you may continue the same line below, if the previous one ended with a single backslash:

 var oneLine = """
               This is one \
                 line of text!""";

Result:

This is one   line of text!

Enjoy ;)

You can play with the output right away in an online Java 17+ compiler: https://www.jdoodle.com/online-java-compiler/


NOTE: If using in Java 13(14), the feature was preview, there. So you could not use it in Java 13(14), unless you set the --enable-preview TextBlock key.