Close Menu
MKOVAH Magazine
    Facebook X (Twitter) Instagram
    MKOVAH Magazine
    • Home
    • Technology
    • Digital World
    • Business
    • Automotive
    MKOVAH Magazine
    Home»Technology»Java Records in Java 16: Syntax, Features, and Examples
    Technology

    Java Records in Java 16: Syntax, Features, and Examples

    TiagoBy TiagoSeptember 12, 202610 Mins Read
    Share Facebook Twitter Pinterest LinkedIn WhatsApp Reddit Tumblr Email
    Understanding Java Records From Java 16
    Share
    Facebook Twitter LinkedIn Pinterest Email

    Java records provide a concise way to create classes whose primary purpose is to store immutable data. Although records first appeared as a preview feature in Java 14, they became a permanent part of the language with the release of Java 16.

    Before records, developers often had to write constructors, accessor methods, and standard object methods manually. lerecords remove much of this repetitive code while preserving clear structure, type safety, and readability.

    What Are Java Records?

    A record is a special type of Java class designed to represent a fixed collection of data. It automatically generates several common class members based on the components declared in its header.

    A Java record automatically provides:

    • Private final fields for its components
    • A public constructor
    • Public accessor methods
    • An equals() method
    • A hashCode() method
    • A readable toString() method

    According to the official JDK 16 documentation, records became a permanent Java language feature in Java 16 after being introduced and refined through earlier preview releases.

    Traditional Java Class vs Java Record

    Consider a simple class that stores a user’s name and age.

    public final class User {
        private final String name;
        private final int age;
    
        public User(String name, int age) {
            this.name = name;
            this.age = age;
        }
    
        public String getName() {
            return name;
        }
    
        public int getAge() {
            return age;
        }
    
        @Override
        public boolean equals(Object obj) {
            // Equality implementation
        }
    
        @Override
        public int hashCode() {
            // Hash code implementation
        }
    
        @Override
        public String toString() {
            return "User[name=" + name + ", age=" + age + "]";
        }
    }
    

    This class requires considerable boilerplate code. The same data model can be written as a Java record in a single line:

    public record User(String name, int age) {
    }
    

    The Java compiler automatically creates the constructor, component fields, accessor methods, equals(), hashCode(), and toString().

    Basic Syntax of a Java Record

    The general syntax of a record is:

    public record RecordName(Type componentName) {
    }
    

    Here is an example with multiple components:

    public record Product(
        long id,
        String name,
        double price
    ) {
    }
    

    A new Product record can be created like this:

    Product product = new Product(101, "Laptop", 899.99);
    

    Its values are accessed through component accessor methods:

    System.out.println(product.id());
    System.out.println(product.name());
    System.out.println(product.price());
    

    Unlike conventional JavaBeans, record accessors do not begin with get. For example, a record uses product.name() rather than product.getName().

    Understanding Record Components

    The values listed inside the record header are called record components.

    public record Employee(
        int employeeId,
        String employeeName,
        String department
    ) {
    }
    

    For each component, Java automatically creates:

    • A private final field
    • A public accessor method with the same name
    • A matching parameter in the canonical constructor

    The fields are final, meaning their references cannot be reassigned after the record object has been created.

    Are Java Records Immutable?

    Java records are shallowly immutable. Their component fields are final, so they cannot be assigned new values after construction.

    For example:

    User user = new User("David", 30);
    
    // This is not allowed
    // user.name = "Michael";
    

    However, a record may contain a reference to a mutable object such as a list.

    public record Team(String name, List<String> members) {
    }
    

    Although the members reference cannot be replaced, the original list may still be modified:

    List<String> names = new ArrayList<>();
    names.add("Ali");
    
    Team team = new Team("Development", names);
    names.add("Sara");
    

    The record now reflects the modified list. Developers who need stronger immutability should create a defensive copy.

    public record Team(String name, List<String> members) {
        public Team {
            members = List.copyOf(members);
        }
    }
    

    This prevents outside code from modifying the record’s internal list through the original reference.

    Constructors in Java Records

    Records support different forms of constructors, including canonical and compact constructors.

    Canonical Constructor

    A canonical constructor includes parameters that match every record component.

    public record Account(String username, double balance) {
    
        public Account(String username, double balance) {
            if (username == null || username.isBlank()) {
                throw new IllegalArgumentException("Username is required");
            }
    
            if (balance < 0) {
                throw new IllegalArgumentException("Balance cannot be negative");
            }
    
            this.username = username;
            this.balance = balance;
        }
    }
    

    This constructor provides complete control over validation and field assignment.

    Compact Constructor

    A compact constructor removes the parameter list and automatic field assignments from the source code.

    public record Account(String username, double balance) {
    
        public Account {
            if (username == null || username.isBlank()) {
                throw new IllegalArgumentException("Username is required");
            }
    
            if (balance < 0) {
                throw new IllegalArgumentException("Balance cannot be negative");
            }
        }
    }
    

    Java automatically assigns the validated parameters to their corresponding fields after the compact constructor body finishes.

    Adding Methods to a Record

    Records are not limited to storing values. They can contain instance methods, static methods, static fields, and nested types.

    public record Rectangle(double width, double height) {
    
        public double calculateArea() {
            return width * height;
        }
    
        public boolean isSquare() {
            return width == height;
        }
    }
    

    Usage:

    Rectangle rectangle = new Rectangle(10, 5);
    
    System.out.println(rectangle.calculateArea());
    System.out.println(rectangle.isSquare());
    

    This allows records to keep behavior close to the data it represents.

    Static Members in Java Records

    A record cannot declare additional instance fields, but it can contain static fields and methods.

    public record Currency(String code, String symbol) {
    
        public static final Currency USD =
            new Currency("USD", "$");
    
        public static Currency defaultCurrency() {
            return USD;
        }
    }
    

    Static members are useful for constants, factory methods, and operations that do not depend on a specific record instance.

    Customizing Accessor Methods

    The automatically generated accessor methods can be customized when necessary.

    public record Person(String name) {
    
        @Override
        public String name() {
            return name.trim();
        }
    }
    

    The custom method must return the same type as the declared component. Developers should use customized accessors carefully because unexpected transformations can make record behavior less predictable.

    Implementing Interfaces With Records

    A Java record can implement one or more interfaces.

    public interface Printable {
        void print();
    }
    
    public record Invoice(
        String invoiceNumber,
        double total
    ) implements Printable {
    
        @Override
        public void print() {
            System.out.println(
                "Invoice: " + invoiceNumber + ", Total: " + total
            );
        }
    }
    

    This makes records useful in systems that depend on interface-based design.

    Can Java Records Extend Other Classes?

    A record cannot explicitly extend another class because every record implicitly extends java.lang.Record.

    The following declaration is not allowed:

    // Invalid Java code
    public record User(String name) extends Person {
    }
    

    Records are also implicitly final, which means another class cannot extend a record.

    // Invalid Java code
    public class Admin extends User {
    }
    

    A record can still implement interfaces, making composition and interface-based programming the preferred approaches.

    Equality in Java Records

    Java records automatically implement value-based equality. Two record objects are equal when they are created from the same record type and their corresponding component values are equal.

    User firstUser = new User("Emma", 25);
    User secondUser = new User("Emma", 25);
    
    System.out.println(firstUser.equals(secondUser));
    

    Output:

    true
    

    The generated hashCode() method follows the same component-based logic, making records suitable for use as keys in hash-based collections when their components are appropriate for that purpose.

    The Generated toString() Method

    Records automatically generate a readable toString() representation.

    User user = new User("Emma", 25);
    System.out.println(user);
    

    Typical output:

    User[name=Emma, age=25]
    

    This is particularly useful during development, testing, debugging, and logging.

    Annotations and Java Records

    Annotations can be applied to record declarations and components.

    public record Customer(
        @NotNull String name,
        @Email String email
    ) {
    }
    

    Depending on the annotation’s declared target, Java may propagate a component annotation to the generated field, constructor parameter, or accessor method.

    This capability helps records work with validation, serialization, documentation, and persistence frameworks, provided those frameworks support records correctly.

    Common Use Cases for Java Records

    Java records work best when a type primarily represents data rather than a complex mutable entity.

    Common applications include:

    Data Transfer Objects

    Records can represent information transferred between application layers.

    public record UserResponse(
        long id,
        String username,
        String email
    ) {
    }
    

    API Request and Response Models

    Records are useful for REST API payloads when the framework and serialization library support them.

    public record LoginRequest(
        String username,
        String password
    ) {
    }
    

    Database Query Results

    A record can represent a read-only projection returned by a database query.

    public record SalesSummary(
        String region,
        long orderCount,
        double totalRevenue
    ) {
    }
    

    Configuration Values

    Records can group related configuration values into a clear type.

    public record ServerConfig(
        String host,
        int port,
        boolean secure
    ) {
    }
    

    Compound Map Keys

    Because records automatically implement consistent equality and hashing, they can work well as multi-value map keys.

    public record LocationKey(
        String country,
        String city
    ) {
    }
    

    Limitations of Java Records

    Records are convenient, but they are not suitable for every class.

    Important limitations include:

    • A record cannot extend another class.
    • A record is implicitly final.
    • Record component fields are final.
    • Additional instance fields cannot be declared.
    • Records provide shallow rather than deep immutability.
    • Generated accessors do not follow traditional JavaBean getter naming.
    • Some older libraries may require extra configuration or may not support records.

    A conventional class may be more appropriate when an object requires inheritance, extensive mutable state, lifecycle management, or a hidden representation that differs significantly from its public data model.

    Records vs Lombok

    Lombok annotations such as @Data and @Value can also reduce boilerplate, but records are a native Java language feature.

    Records offer several advantages:

    • No external dependency is required.
    • Their meaning is recognized by the compiler and JVM.
    • Their structure is standardized.
    • Development tools can understand them consistently.
    • Their generated behavior is clearly defined by Java.

    Lombok remains useful when a project needs conventional classes, configurable code generation, builders, mutable properties, or framework-specific patterns that records do not provide.

    Records vs Regular Classes

    FeatureJava RecordRegular Class
    Boilerplate codeMinimalUsually more
    Component fieldsAutomatically finalDeveloper controlled
    AccessorsAutomatically generatedUsually written manually
    InheritanceCannot extend classesCan extend another class
    Additional instance fieldsNot allowedAllowed
    Best suited forTransparent data carriersComplex objects and behavior
    equals() and hashCode()Automatically generatedUsually implemented manually

    Best Practices for Using Records

    Follow these practices when adding records to a Java application:

    1. Use records for transparent data models with a fixed set of components.
    2. Validate component values in a compact constructor.
    3. Create defensive copies of mutable collections.
    4. Avoid placing excessive business logic inside records.
    5. Do not expose passwords, access tokens, or confidential values through generated toString() output.
    6. Confirm that serializers and frameworks in the project support records.
    7. Choose meaningful component names because they become part of the record’s public API.

    Frequently Asked Questions

    When Were Records Added to Java?

    Records were first introduced as a preview feature in Java 14. They received further refinement and became a permanent language feature in Java 16.

    Do Java Records Require Java 16?

    Permanent record support begins with Java 16. Earlier preview implementations required preview-feature settings and should not be treated as the final standardized version.

    Do Records Generate Getter Methods?

    Records generate accessor methods, but they do not use the conventional get prefix. A component named email creates an email() accessor rather than getEmail().

    Can a Java Record Have a Constructor?

    Yes. A record may declare a canonical constructor, compact constructor, and additional overloaded constructors. Any alternative constructor must eventually invoke the canonical constructor.

    Can a Record Contain Null Values?

    Yes. Records permit null reference values unless validation in the constructor rejects them.

    Can Records Be Serialized?

    Records can work with Java serialization and many JSON libraries. Actual compatibility depends on the library and version being used, so framework support should be verified before adoption.

    Are Java Records Faster Than Regular Classes?

    Records are primarily a language-design and code-maintenance feature. Developers should not assume that replacing a regular class with a record will automatically produce a meaningful performance improvement.

    Conclusion

    Java records in Java 16 offer a clear and compact way to model immutable data carriers. By generating constructors, accessors, equality methods, hash codes, and string representations automatically, records reduce repetitive code without sacrificing type safety.

    They are particularly effective for DTOs, API models, query results, configuration objects, and compound keys. However, conventional classes remain the better option when a design requires inheritance, mutable state, extra instance fields, or strict control over internal representation. Choosing records for the right data-focused use cases can make a Java codebase shorter, clearer, and easier to maintain.

    Share. Facebook Twitter Pinterest LinkedIn WhatsApp Reddit Tumblr Email
    Previous ArticleMicroservices Design Patterns: Key Architecture Patterns Every Developer Should Know
    Next Article Types of Sensors and Actuators in IoT Explained
    Tiago
    • Website

    Related Posts

    Types of Sensors and Actuators in IoT Explained

    September 12, 2026

    Microservices Design Patterns: Key Architecture Patterns Every Developer Should Know

    September 11, 2026

    C# String Formatting Examples: Practical Ways to Format Strings

    September 11, 2026
    View 2 Comments

    2 Comments

    1. Pingback: Types of Sensors and Actuators in IoT Explained

    2. Pingback: Formatting Strings in Java: String.format() Method

    Leave A Reply Cancel Reply

    Search…
    Recent Posts

    Formatting Strings in Java: String.format() Method

    September 12, 2026

    Types of Sensors and Actuators in IoT Explained

    September 12, 2026

    Java Records in Java 16: Syntax, Features, and Examples

    September 12, 2026

    Microservices Design Patterns: Key Architecture Patterns Every Developer Should Know

    September 11, 2026

    C# String Formatting Examples: Practical Ways to Format Strings

    September 11, 2026

    Databricks Disk Cache: The Secret to Faster Repeated Analytics Workloads

    September 11, 2026
    About

    MKOVAH Magazine is your destination for fresh ideas, useful insights, and the latest trends across technology, business, lifestyle, travel, entertainment, health, and more. We bring engaging and informative content to help you stay inspired, informed, and connected with the world around you.

    Latest Posts

    Types of Sensors and Actuators in IoT Explained

    September 12, 2026

    Java Records in Java 16: Syntax, Features, and Examples

    September 12, 2026

    Microservices Design Patterns: Key Architecture Patterns Every Developer Should Know

    September 11, 2026
    Contact Us

    Our team is always available to support you and ensure you receive the help you need.

    Mail: tech4links@gmail .com
    Whatsapp: Whatsapp

    Address: Flat No. 504, Shanti Residency, MG Road, Andheri East, Mumbai, Maharashtra, India

    • About Us
    • Disclaimer
    • Privacy Policy
    • Terms & Conditions
    • Write For Us
    • Contact Us
    • Sitemap
    © 2026 | MKOVAH Magzine | All Rights Reserved

    Type above and press Enter to search. Press Esc to cancel.