Records Flashcards
Defining a record
public record Crane (int numberEggs, String name) {}
* record keyword
* record name
* list of fields serrounded by parentheses
* May declare optional constructors, methods, and constants
records are also implicitly final. The final modifier is optional but assumed.public final record Crane(int numberEggs, String name) {}
can’t extend or inherit a record.public record BlueCrane() extends Crane {} // DOES NOT COMPILE
a record can implement a regular or sealed interface, provided it implements all of the abstract methods.
~~~
public interface Bird {}
public record Crane(int numberEggs, String name) implements Bird
{}
~~~
Members Automatically Added to Records
- Constructor: A constructor with the parameters in the same order as the record declaration
- Accessor method: One accessor for each field
- equals(): A method to compare two elements that returns true if each field is equal in terms of equals()
- hashCode(): A consistent hashCode() method using all of the fields
- toString(): A toString() implementation that prints each field of the record in a convenient, easy-to-read format
Long Constructor
We can declare the constructor the compiler normally inserts automatically, which we refer to as the long constructor.
public record Crane(int numberEggs, String name) { public Crane(int numberEggs, String name) { if (numberEggs < 0) throw new IllegalArgumentException(); this.numberEggs = numberEggs; this.name = name; } }
The compiler will not insert a constructor if you define one with the same list of parameters in the same order. Since each field is final, the constructor must set every field. For example, this record does not compile:
public record Crane(int numberEggs, String name) { public Crane(int numberEggs, String name) {} // DOES NOT COMPILE }
Compact Constructors
public Crane { public Crane { if (numberEggs < 0) throw new IllegalArgument Exception(); name = name.toUpperCase(); } }
- No parenthese or constructor parameters
- custom validation
- Refers to input parameters (not instance members, cannot modify the instance members)
- Long constructor implicitly called at the end of compact constructor
- Compact constructors give you the opportunity to apply transformations to any of the input values.
- Java calls the full constructor after the compact constructor but with the modified constructor parameters.
Overloaded Constructors
public record Crane(int numberEggs, String name) { public Crane(String firstName, String lastName) { this(0, firstName + " " + lastName); } }
After the first line, all of the fields will already be assigned, and the object is immutable.
public record Crane(int numberEggs, String name) { public Crane(int numberEggs, String firstName, String lastName) { this(numberEggs + 1, firstName + " " + lastName); numberEggs = 10; // NO EFFECT (applies to parameter, not instance field) this.numberEggs = 20; // DOES NOT COMPILE } }
you also can’t declare two record constructors that call each other infinitely or as a cycle.
public record Crane(int numberEggs, String name) { public Crane(String name) { this(1); // DOES NOT COMPILE } public Crane(int numberEggs) { this(""); // DOES NOT COMPILE } }
Customizing Records
Records actually support many of the same features as a class. Here are some of the members that records can include and that you should be familiar with for the exam:
* Overloaded and compact constructors
* Instance methods including overriding any provided methods (accessors, equals(), hashCode(), toString())
* Nested classes, interfaces, annotations, enum, and records
While you can add methods, static fields, and other data types, you cannot add instance fields outside the record declaration, even if they are private. Doing so defeats the purpose of using a record and could break immutability!
Records also do not support instance initializers
. All initialization for the fields of a record must happen in a constructor.