Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.syntblaze.com/llms.txt

Use this file to discover all available pages before exploring further.

A Java record is a restricted, implicitly final class designed to act as a transparent carrier for immutable data. Introduced as a standard feature in Java 16, it eliminates boilerplate by automatically generating the standard members required for data-centric classes based entirely on its state description (the record header). When you declare a record, you define its components in the header:
public record Point(int x, int y) { }
Based on this declaration, the Java compiler automatically generates the following bytecode equivalents:
  1. State: A private final field for each component defined in the header (x and y).
  2. Constructor: A canonical constructor whose signature exactly matches the record components, assigning each argument to its corresponding field.
  3. Accessors: Public read accessor methods named exactly after the components (e.g., x() and y(), rather than getX() and getY()).
  4. Object Methods: Implementations of equals(), hashCode(), and toString() that operate on all components defined in the header.

Constructor Customization

Records support a specialized compact constructor. This constructor omits the parameter list and is primarily used for validation or normalization before the canonical constructor implicitly assigns the parameters to the fields.
public record User(String username, int age) {
    
    // Compact constructor
    public User {
        if (age < 0) {
            throw new IllegalArgumentException("Age cannot be negative");
        }
        if (username != null) {
            username = username.trim(); // Normalization
        }
        // The compiler implicitly inserts:
        // this.username = username;
        // this.age = age;
    }
}
You can also declare overloaded constructors, provided they ultimately delegate to the canonical constructor using this(...).
public record User(String username, int age) {
    // Overloaded constructor delegating to the canonical constructor
    public User(String username) {
        this(username, 0); 
    }
}

Technical Constraints and Characteristics

Because records are designed with strict semantics regarding immutability and state transparency, they are subject to specific language constraints:
  • Inheritance: All records implicitly extend java.lang.Record. Because Java does not support multiple class inheritance, a record cannot extend any other class.
  • Subclassing: Records are implicitly final. They cannot be declared abstract, and no class can extend a record.
  • Interfaces: Records can implement multiple interfaces. The generated methods or custom methods within the record body fulfill the interface contracts.
  • Instance Fields: A record cannot declare any instance fields outside of the components defined in the record header.
  • Static Members: Records can declare static fields, static initializers, and static methods.
  • Instance Methods: You can declare custom instance methods within the record body, or override the implicitly generated methods (like toString() or the accessors), provided the overrides do not compromise the immutable semantics of the record.
  • Serialization: Records serialize and deserialize differently than standard classes. They bypass writeObject, readObject, and default serialization mechanisms, relying exclusively on the canonical constructor to reconstruct the object, making them inherently safer against deserialization attacks.
Master Java with Deep Grasping Methodology!Learn More