Java 14 and IntellJ IDEA


Java 14 and IntellJ IDEA Java 14 has a lot of exciting language features
for us developers – Records, Pattern Matching for instanceof, Text Blocks and Switch Expressions. In this screencast, I’ll cover how to use
these features in IntelliJ IDEA. Let’s get started. Imagine you need to store data for a Person. This should be simple. Create class Person, and add instance variables,
say, name and age to define its state. Use Alt Insert on Windows and Linux and caret
N on macOS to generate code for this class – like constructors, getters and setters,
and methods like toString(), equals() and hashCode()
But how would any other developer know that this class is just a carrier of data, without
reading all the code? Shortening code by deleting methods is not
a good approach – the class instances would not work as expected with collection classes. Let’s see how records can help by introducing
a new type declaration in Java 14. To create a record in IntelliJ IDEA 2020.1,
invoke the ‘New Java Class’ dialog box and select ‘Record (Preview Feature)’
in the type. Fill in the name of the record and define
its components. With just one line of code, you get to define
a record – Person – with two components name and age. Java 14 features are supported in IntelliJ
IDEA 2020.1. Access the Project settings by using Ctrl
+ Alt + Shift + S on Win & Linux/ (command) ; on macOS. Use JDK 14 as your Project SDK and choose
the Project language level as ‘14 (Preview) – Records, patterns, text blocks’ for
your Project and Modules settings. Starting with IntelliJ IDEA 2020.1, you can
also download the JDK from within IntelliJ IDEA and configure it. When you compile a record, instance variables
and methods are added to it automatically. Let’s view the decompiled class to find
out what these members are. Open the Project window by using Alt 1 on
Windows & Linus OS and Command 1 on macOS. Go to folder ‘out’ and click on Person.class
to open it in the editor window): Person is defined as a final class, extending
java.lang.Record class from the Java API. For each of the components of the record Person,
the compiler defines a final instance variable (name and age). A constructor and method toString, hashCode
and equals are also generated automatically for records. The name of the getter method is the same
as that of the data variable (it doesn’t start with ‘get‘ or ‘is‘). Since a record is supposed to be immutable,
no setter methods are defined. You can instantiate a record by using the
operator new. Don’t miss the parameter hints when you
are passing values to the constructor in IntelliJ IDEA:
Let’s call the implicit methods which are defined for records – like toString(), equals(),
hashcode(), and retrieve value of its components. You can also use a record before defining
it. When the code doesn’t compile, choose context
actions using Alt-Enter and select create record. IntelliJ IDEA creates the record for you and
you can add the components. You need to follow a couple of rules when
you work with records. A Record can implement interfaces. You can also add static fields, and instance
or static methods to a record, if you need them:
Let’s talk about what it can’t: It cannot be defined as an abstract class,
because it is an implicitly a final class. It cannot extend another class since it already
extends the java.lang.Record class. You can’t add any instance variables to
it – the state of a record is defined by the components you have in its definition. You can modify the default constructor of
a Record.. to say validate its parameter values. IntelliJ IDEA lets you insert a compact, canonical,
or custom constructor in a record. a compact constructor doesn’t have a parameter
list, not even parentheses. A canonical constructor is the one whose signature
matches with the record’s state description. Let’s define code to check the parameter values
passed to this constructor. A custom constructor lets you choose the record
components you want to pass to the constructor of a record. Going back to the canonical constructor – By
invoking context actions in IntelliJ IDEA (with Alt + Enter), you can easily convert
a canonical constructor to a compact constructor, and vice versa:
After editing a constructor, if you end up without any additional code, IntelliJ IDEA
can detect it and delete it for you. You can also add annotations like NotNull
to record components. In this case, when you instantiate this record
with a null value, you’d get an error. Writing a record to a file and reading it
using the Java File I/O API is simple. Let your record implement the Serializable
interface and you are good to go. By using this code, you can write record Person
to a file and read from it. You can refactor a Record, modifying the order
or types of its components, or their names, add new components or remove existing ones. IntelliJ IDEA 2020.1 introduces a simplified
approach to apply Rename or Change Signature Refactorings. Let’s change the name of the parameter name
to full name. As soon we change the signature, this icon
will appear in the gutter. Click to apply the changes. These changes would refactor the record and
reflect in all its usages. Pattern Matching for instanceof makes code
safe and concise by introducing a pattern variable. In this code, instanceof operator checks whether
reference variable obj is of type String. If the result is true, it defines a variable
s and explicitly casts it to type String. to access its method toUpperCase(). We have an obvious repetition here – compare
obj with String, then cast it to String. Let’s see how Pattern Matching can help. In IntelliJ IDEA 2020.1, invoke context-sensitive
actions on variable s, and select ‘Replace ‘s’ with pattern variable’. This removes redundant code by introducing
the pattern variable, which binds to variable obj – so you don’t need to define another
variable or cast it to another type. Pattern variables are final local variables
that are declared and defined at the same place. pattern variables have limited scope. If you try to access it in the else block,
you’ll receive an error. Though it could be confusing, you can define
s as a field in this class. Now, ‘s’ in the else block refers to the
field s and the s on then block refers to the pattern variable s: The simplicity of Pattern Matching might be
deceptive Let’s see how we can simplify this equals
methods. Let’s start by replacing other with a pattern
variable, Now, let’s simplify this if statement. Let’s check if we could further improve
it. Yes, we can – by choosing to replace if-else
with double &&. Various existing intentions work out of the
box with Pattern Matching in IntelliJ IDEA. For this example, let’s start by introducing
a pattern variable. Now, let’s simplify this if statement by replacing
if-else with double &&. At the end, let’s apply the same intention
again – replacing if-else with double &&. The real strength of Pattern Matching for
instanceof lies in how you can use it with various other intentions in IntelliJ IDEA. In this example, let’s start by merging nested
ifs Next, Replace letterNode with pattern variable
For nested if here, let’s apply ‘Merge nested ifs again
Now, Replace the loop with Collection. removeIf
And, at the end, Inline the variable list. (ctrl+Alt+N)
The code now looks concise, simple to read and understand. Let’s see how you can simplify a code block
which has multiple occurrences of instanceof. To look for places where you can use Pattern
Matching for instanceof, spot usages of the instanceof operator and explicit casting of
variables. For this example, let’s start by introducing
a pattern variable, then merging if statements, followed by Inlining of a variable, introducing
pattern variable again and finishing of with merging id statements again, This looks neat,
doesn’t it? If you don’t need the pattern variables,
you can inline them with ‘Inline pattern variable’ refactoring. Use the shortcut Ctrl+Alt+N on Win and Linux/
Option Command N on macOS. After you do so, all its usages would be replaced
with explicit casting Let’s see how extract variable refactoring
works with Pattern Matching with instanceof. If you extract a variable from a cast expression,
and IDEA detects that there were instanceof check before, then instead of creating a new
local variable it just converts the instanceof to the pattern. Released with Java 13, Text Blocks let you
define multi-line Strings easily – without any clutter. This JSON value needs a lot of concatenation
operators or escape sequences so that it can be stored as a String. Not anymore with TextBlocks. In IntelliJ IDEA, you can easily convert a
String to a TextBlock by using Alt+Enter to invoke context-aware actions – and choose
to replace with Text Block. This code is so easy to read. For detailed coverage on how to use Text Blocks,
refer to our previous video and blog – ‘Java 13 and IntelliJ IDEA’. In this screencast, I’ll cover changes to
TextBlocks in Java 14, that is, addition of two new escape sequences. By default, Text Blocks added a newline character
at the end of a line. In Java 14, you can suppress it by using the
backslash. Also, the spaces at the end of a line in text
blocks are removed. To insert them, you can use this escape sequence. With switch expressions, Java 12 enhanced
switch statements – now it can also be used as an expression that can return a value. This is the old switch statement, which you
can convert to the new switch expressions, – The new format is concise, it doesn’t
has a default fall through, you can define multiple constants in the same switch branch. Also, it can return a value from a branch
by using yield. For more details on how to use Switch expressions,
please refer to our previous video and blog – ‘Java 13 and IntelliJ IDEA’. We love to hear from our users. Don’t forget to submit your feedback on
the support of Java 14 features in IntelliJ IDEA. Thanks for watching.

10 Comments

  1. Please, add a way to configure preview features using gradle projects. Every time I refresh gradle file, the project remove the extra features that I set like in the video (reproducible on JDK 13 and 14)

  2. It’s nice to see java slowly catching up with Kotlin/swift and other modern languages.

    But unfortunately, many companies are not even on java 11 yet.

    Better off switching to kotlin with all of these features and seamless java interop.

Leave a Reply

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