Java 13 and IntelliJ IDEA

With Text Blocks, Java 13 is making it easier for you to work with multi-line String values. You would no longer need concatenation operators or escape sequences for your HTML, XML, JSON, or SQL queries, stored as String values.

Java 13 has also modified the Switch Expressions, which was released with Java 12.

In this blog, you’ll cover how to use the language changes introduced with Java 13, in IntelliJ IDEA 2019.3. If you can’t migrate your code to Java 13 to use Text Blocks, this blog will also cover how to use language or reference injections, so that you can edit multi-line String values with ease, irrespective of the Java version you are using.

Let’s get started with the pain points that are being taken care of with Text Blocks.

Multi-line String values prior to Java 13

Imagine you had to store the following JSON text in your Java code:

One of the ways to store it is to use a multi-line String value, as follows:

It is easy to notice how the values and the code that store it, are not the same. You need concatenation operators at the end of each line. To use double quotes within a String value, it must be escaped using a backslash (since is also used as a delimiter for String value). To retain the formatting of the JSON object, you also need to add whitespaces like new line, tabs or spaces. This format is not simple to write, read or edit. Text blocks are here to help.

Using Text blocks

Text Blocks, or multiline String values, are simple to create, read and edit. A preview language feature, they avoid the need of using concatenation operators and (most) escape sequences for String values that span more than one line.

With Text Blocks you can store the multiline String values, as follows:

Here’s capturing the journey – from the pain points of defining multiline String values to the ease of using Text Blocks:

Text Block delimiter

Unlike the double quotes (") used by the traditional String values, Text Blocks use three double quotes (""") as it’s opening and closing delimiters. The text block content gets appropriate indent right from the start:

A quick rule to follow here – The opening delimiter can be followed by zero or more whitespaces, but it must be followed by a line terminator. A Text block value begins ‘after’ this line terminator.

IntelliJ IDEA can detect this missing line terminator and prompt you to correct it:

Where to use Text Blocks

In the preceding sections, we used Text Blocks to store JSON and SQL query. You could also use Text Blocks to store values that usually span multiple lines like – XML, HTML, or code. You can also use them for plain long String values that span multiple lines, without using the concatenation operators.

Here’s an example of a Text Block storing a HTML value:

And here’s just a long line of String, stored using Text Blocks:

Text Blocks take off the visual clutter from multiline strings which existed in the form of concatenation operators and escape sequences. Also, IntelliJ IDEA 2019.3 makes it easier for you to adopt this new language feature.

What about the incidental white spaces

You would usually add spaces to your values to align them vertically in your code. What rules does the compiler follow to include or exclude these white spaces? In Text Blocks, the leftmost non-whitespace character on any of the lines or the leftmost closing delimiter defines where meaningful white space begins. IntelliJ IDEA helps you view this position – using a vertical line – a feature that I absolutely love about Text Block’s support in IntelliJ IDEA.

Here’s how the vertical bar in IntelliJ IDEA lets you visualize the starting position of your Text Block values. By default, the trailing white spaces are removed in Text Block values. To add them forcefully, you can use \040:

Not a String variation

Java isn’t adding a variation of type String with Text Blocks. They are compiled to regular String instances (java.lang.String). This essentially means that you can call all String methods on it:

You can also invoke Context Actions to convert a Text Block to a regular String literal and vice-versa:

Formatting Text Blocks

You can align your uneven Text Blocks with ease. Use Extend Selection (Ctrl + W) to quickly select the text block contents. You can either use Reformat File Dialog (Shift + Ctrl + Alt + L) and Run it, or invoke Context Actions using Alt + Enter. Select ‘Adjust code style settings’, followed by ‘Align when multiline’, and invoke ‘Save’:

When you copy-paste text from a regular string literal to Text Blocks, you get an option to remove the unnecessary escapes. If you apply batch migration from concatenation to text block, then all redundant escapes are removed automatically:

Concatenation of Text Blocks, regular string literals or variable values can result in not-so-readable code. You can choose from multiple options to improve its readability. Invoke Context Actions (Alt + Enter), and choose from multiple options. You can choose ‘Replace + with String.format()’, or ‘Replace + with java.text.MessageFormat.format()’ to make your concatenated values more readable:

Also, it is simple to replace a concatenation of text blocks with a single text block, by invoking Context Actions (Alt + Enter) and choosing ‘Join concatenated string literals’:

Switch expressions

Switch expressions were introduced with Java 12. With switch expressions, Java enhanced one of its basic language constructs – switch – to improve everyday coding experience for developers. Benefits were multifold. As compared to the ‘traditional’ switch constructs, switch expressions can return a value. The ability to define multiple constants with a switch branch, and improved code semantics, made it concise. By removing default fall-through switch branches, you are less likely to introduce a logical error in a switch expression.

We covered Switch Expressions in detail, in a previous blog when Java 12 was released.

Java 13 includes only one change to the Switch Expressions – it now uses the yield statement to return a value from a switch branch. When Switch Expressions were introduced with Java 12, it used the keyword break to return values from a switch branch.

IntelliJ IDEA 2019.3 also adds inspections to help you with using Switch Expressions better. For example, it includes the generation of missing switch branches, based on the data flow in your code:

Preview Language features

Text blocks have been released with Java 13 as a preview language feature. Switch Expressions were introduced in Java 12 as a preview language feature. Though they are modified in Java 13, it still remains as a preview feature. This essentially means that both these features and their finer details could change in a future Java release, depending on the feedback received on this feature by Oracle.

Preview language features are not incomplete or half-baked features. With the new six-month release cadence, it is crucial for Oracle to let developers work with these features and share if there are any issues with them. Feedback is essential – it lets Oracle refine a language change before adding it to the Java language. It is important to note that once a feature is made permanent in the language – it isn’t feasible to take it off.

At JetBrains, we support preview features from the latest Java version and upcoming release, if feasible. IntelliJ IDEA 2019.3 supports Text Blocks and Switch Expressions as preview language features for Java 13. IntelliJ IDEA 2019.3 no longer supports Switch Expressions as a preview Language feature when configured to work with Java 12 because Switch Expressions have been modified in Java 13.

If you have any feedback on these features, you can voice your opinions here.

IntelliJ IDEA Configuration

To work with Text Blocks and Switch Expressions in IntelliJ IDEA 2019.3, download JDK 13 and configure it to be used with IntelliJ IDEA. To use preview language features, they should be enabled using compilation and runtime parameters. In IntelliJ IDEA 2019.3, this is done behind the scenes, when you select your Project JDK as 13 and language level as ‘13 (Preview) – Switch expressions, text blocks’, in Project Structure:

Language or Reference Injection in IntelliJ IDEA

Language or Reference injection in IntelliJ IDEA lets you edit multiline string values with ease. You can choose from multiple ranges of values here – from .getIgnore, AngularJS, CSS, Kotlin, SQL and many more options.

This option applies to all String values – traditional String and Text Blocks.

Since Text Blocks is removing the visual clutter, this option will be more helpful with traditional String values. When chosen, it edits the string values in a separate window, with code completion, error detection, testing values, and many others. You could also language injections to verify correct regex values, without leaving your editor.

Place your cursor within your String, use Alt+Enter to show ‘Context Actions’. Select ‘Inject Language or Reference’ and view the list of available options:

Summary

IntelliJ IDEA sets a high bar for itself, in terms of supporting new Java features. It doesn’t just support basics like error highlighting and code completion, but also automatic migration to new code constructs. IntelliJ IDEA also adapts its existing set of inspection and code assistance tools so that they correctly interact with new features.

Java 13 is here and the latest IntelliJ IDEA release, that is, 2019.3, supports all the preview language features – Text Blocks and Switch Expressions.

Happy Coding.

This entry was posted in New Features, Tutorials and tagged , , , , , . Bookmark the permalink.

5 Responses to Java 13 and IntelliJ IDEA

  1. Christopher Rucinski says:

    How does refactoring a long variable name to a shorter one affect the spacing of text?

    Is the whole Text Block shifted to the left? Or is the Text Block remaining in place and there is now added “indents”/margin?

  2. Rob Crawford says:

    Anyone else spot the SQL injection vulnerability?

    • Rob Crawford says:

      Actually, on second thought, the refactored version is OK — it would likely still get called out by most automated tools, but it at least is forcing the parameter to be numeric.

      • Philip G says:

        If you are talking about the getQuery() method, as the parameter raise is an Integer, no SQL injection is possible. Even in the original version :-)

        • Bobby Tables says:

          It would still be better to use parameter binding though; otherwise the DBMS has to parse the SQL statement every time it gets executed.

Leave a Reply

Your email address will not be published. Required fields are marked *