Java records were introduced in Java 14 as a new type of class that aims to simplify the creation of classes that are primarily used to store data. Records are concise, immutable, and come with built-in behavior that makes them easy to use and understand. In this article, we’ll take a closer look at Java records and how they can be used in your Java projects.
What are Java Records?
Java records are a new type of class introduced in Java 14 that allow you to create classes that are primarily used to store data. Records are similar to classes in that they can have fields, constructors, and methods, but they come with built-in behavior that makes them easier to use and understand.
One of the key features of Java records is that they are immutable by default. This means that once a record object is created, its values cannot be changed. This makes them ideal for representing data that should not be modified after creation, such as configuration settings or data objects passed between layers of an application.
Another key feature of Java records is that they have a concise syntax that makes them easy to create and use. Let’s take a look at an example:
public record Person(String name, int age) {}
This record defines a Person
class with two fields, name
and age
. The record
keyword is used to define the class as a record, and the fields are specified in the constructor parameter list. Records also come with a built-in implementation of equals()
, hashCode()
, and toString()
methods based on their fields.
Let’s take a closer look at each of these features.
Immutable by Default
As mentioned earlier, Java records are immutable by default. This means that once a record object is created, its values cannot be changed. This is enforced by making the fields of the record final
and assigning their values in the constructor.
For example, if we create a Person
record:
Person p = new Person("Alice", 25);
We can’t change the values of its fields:
p.name = "Bob"; // compile error: cannot assign a value to final variable name p.age = 30; // compile error: cannot assign a value to final variable age
This makes records ideal for representing data that should not be modified after creation, such as configuration settings or data objects passed between layers of an application.
Concise Syntax
Another key feature of Java records is their concise syntax. As we saw earlier, a record can be defined in a single line of code:
public record Person(String name, int age) {}
This defines a Person
record with two fields, name
and age
. The fields are specified in the constructor parameter list, and the record
keyword is used to define the class as a record.
The concise syntax of records makes them easy to create and use, and can help reduce boilerplate code in your applications.
Built-in Methods
Java records come with built-in implementations of equals()
, hashCode()
, and toString()
methods based on their fields. This means that you don’t need to write these methods yourself, and they will work as expected out of the box.
For example, if we create two Person
records with the same values:
Person p1 = new Person("Alice", 25); Person p2 = new Person("Alice", 25);
The equals()
method will return true
:
System.out.println(p1.equals(p2)); // prints "true"
This is because the equals()
method is based on the values of the fields, and the fields of p1
and p2
are the same.
Similarly, the hashCode()
method is based on the values of the fields, so two records with the same field values will have the same hash code:
System.out.println(p1.hashCode() == p2.hashCode()); // prints "true"
Finally, the toString()
method is implemented to return a string representation of the record’s fields:
System.out.println(p1.toString()); // prints "Person[name=Alice, age=25]"
These built-in methods make records easy to use and understand, and can help reduce the amount of boilerplate code in your applications.
Using Java Records in Your Projects
Now that we’ve seen what Java records are and how they work, let’s take a look at how you can use them in your Java projects.
Defining a Record
To define a record, you use the record
keyword followed by the name of the record and its fields in the constructor parameter list:
public record Person(String name, int age) {}
This defines a Person
record with two fields, name
and age
. The fields are specified in the constructor parameter list, and the record
keyword is used to define the class as a record.
Creating an Instance of a Record
To create an instance of a record, you use the new
keyword followed by the name of the record and the values of its fields:
Person p = new Person("Alice", 25);
This creates a new Person
record with the name “Alice” and age 25.
Accessing Fields
You can access the fields of a record using their names:
System.out.println(p.name()); // prints "Alice" System.out.println(p.age()); // prints "25"
This prints the value of the name
and age
fields of the Person
record.
Comparing Records
You can compare records using the equals()
method, which is based on the values of their fields:
Person p1 = new Person("Alice", 25); Person p2 = new Person("Alice", 25); System.out.println(p1.equals(p2)); // prints "true"
This prints true
because the fields of p1
and p2
have the same values.
Changing the Behavior of Built-in Methods
You can change the behavior of the built-in methods by defining your own implementations in the record:
public record Person(String name, int age) { @Override public String toString() { return name + " (" + age + ")"; } }
This overrides the default toString()
method to return a string representation of the Person
record with the name and age in parentheses.
Using Records in Collections
Records can be used in collections just like any other Java class:
List<Person> people = List.of( new Person("Alice", 25), new Person("Bob", 30), new Person("Charlie", 35) );
This creates a list of Person
records that can be accessed and manipulated like any other list.
Conclusion
Java records are a powerful new feature that simplify the creation of classes that are primarily used to store data. They are concise, immutable, and come with built-in behavior that makes them easy to use and understand. By using Java records in your projects, you can reduce the amount of boilerplate code in your applications and make your code more readable and maintainable.