One way that we can store immutable data is to use a record. A record is a reference type that allows you to create your own immutable data type where multiple pieces of related data are stored together. We can use one variable to be assigned to a record object rather than using multiple variables.
To create a record data type, you need to use the following pattern:
When we create a record, the data values that are being grouped together are listed in parenthesis after the name of the record. Each data value in the list is separated by a comma (,
). This list is called a record component list. A record component list contains the data type and variable name for each value included in the record as well as defines a way to access these values.
Vehicle Record Example
For example, a record to represent the year, make and model of a vehicle, would look like the following:
Representing a Point
A point in a two-demensional space consists of:
- an x coordinate
- a y coordinate
In this example, the data type used for the x and y coordinates are defined as type double
.
We could create two separate variables, like the following:
double x;
double y;
But the better way to do this is to create a new data type using a record. The data involved in a point is immutable.
The Point
record would be as follows:
record Point(double x, double y) {
}
Representing an Address
A mailing address in the United States consists of:
- a street address, which can be two lines of text,
- a city,
- a state,
- a zip code, which can be either 5 digits or 5 digit followed by a dash and 4 more digits.
In this example, we are choose to represent all of the pieces of data are of type String
.
We could create five separate variables, like the following:
String street1;
String street2;
String city;
String state;
String zipCode;
If we had to store multiple addresses, like for a database, we would need to create five variables for each address. A better way to do this is to create a new data type using a record. The data involved in a mailing address is immutable. While the person living at the address might change, the address itself does not. With a record, we would only need one variable for each address object we are storing in the program.
The Address record would be as follows:
record USAddress(String street1, String street2, String city, String state, String zip) {
}
Representing a Bank Account
A bank account consists of:
- Type of account (savings or checking account),
- Account Owner's Name,
- Bank Routing Number,
- Bank Account Number.
A bank would need to store the bank account information for many bank accounts. Using multiple variables for each bank account would mean needing a way to group the information for each account together. Since this information is immutable, a record is an ideal way to store this information all in one bank account object.
In this example, the type of account is being represented as a String
. The account owner's name could be a String
or it could be a collection of data that represents a profile for the customer, like the customer name, address, phone number, email address, etc.
The bank routing number and bank account number could start with a 0
in some cases, so we will use a String
to represent the account number.
The bank account record would be as follows:
record BankAccount(String accountType, String ownersName, String routingNumber, String accountNumber) {
}
Representing a Restaurant Receipt
A restaurant receipt might consists of:
- The server's name,
- The food total,
- The tip amount,
- The total bill.
In this example, the server's name is being represented as a String
.
The food total, tip amount, and total bill are being represented as type double
.
The restaurant receipt record would be as follows:
record RestaurantReceipt(String serverName, double foodBill, double tipAmount, double totalBill) {
}
Declaring and Initializing a Record Object
A specific instance of a record is called an object. Recall, an object is an instance of a class and a record is a type of class. We can declare and initialize many objects or instances of a class.
When we created a String
object, we did this using a String
literal and the statement looked very similar to other variable declaration and initializations we have been doing. However, with many other objects, they must be created using the class's constructor.
A constructor is used to create an object and initialize the values for the object. A constructor always has the same name as the class.
When creating an object using a constructor, the Java keyword new
is used. Since a record is a type of class, we can create an object of a record type using the following pattern:
The values in parenthesis are called arguments. When we create and object or instance of a record, each component in the record component list will need a corresponding argument. These are the values for the components and essentially assigns the component to the value of the argument. The arguments are the same type as the component and are listed in the same order. The arguments are separated by a comma (,
). Consider the following example of creating the object myCar
.
The arguments "2020", "Toyota", "Camry"
are being passed to the components String year, String make, String model
as follows:
Order of Arguments Matters
If the order of the arguments does not match the order in the record component list, then the wrong values will be assigned. In this case, that could mean confusing data, but in cases where the types do not match, you will get an error.
Using our RestaurantReceipt
record as follows:
record RestaurantReceipt(String serverName, double foodBill, double tipAmount, double totalBill) {
}
If we were to attempt to create an object of this type by writing the following:
RestaurantReceipt customer1 = new RestaurantReceipt(20.55, 4.45, 25, "Rachel");
This statement will cause an error. The value 20.55
will be converted to a String
type, but the String
"Rachel"
is unable to be converted to be of type double
.
The correct way to create customer1
is as follows:
RestaurantReceipt customer1 = new RestaurantReceipt("Rachel", 20.55, 4.45, 25);
Records Practice
Let's try it in the Java Playground using the Point
class! You will see that a Point
object has been created with [x=0.0, y=0.0]
Representing a Book
A book consists of:
- Title
- Author
- Publish date
- ISBN number
The data for a Book
are all of type String
.
Let's try it in Java Playground! You will see that a Book
object has been created with [title=Lord of the Rings, author=J. R. R. Tolkien, publishDate=1954, isbn=9-780-61864-0157]
.
Misaligned Parameters
Using our Vehicle
record as follows:
record Vehicle(String year, String make, String model) {
}
If we were to attempt to create an object of this type by writing the following:
Vehicle myCar = new Vehicle("Jeep", "Renegade", 2020);
The value 2020
cannot be assigned to a String
type.
Let's look at another example. If we were to attempt to create an object of this type by writing the following:
Vehicle myCar = new Vehicle("Jeep", "Renegade", "2020");
Additionally, year
would be assigned "Jeep"
, make
would be assigned "Renegade"
, and model
would be assigned "2020"
.
Modify the code to update the order of the parameters so that the object myCar
is created correctly.
Resources
Next Learn Tutorial
Learn: Arithmetic Expressions and Assignments