Can a record have custom constructors, methods and validation?

Yes. A record can have a compact constructor for validation or normalisation, extra constructors that delegate to the canonical one, instance methods, static fields and static factory methods. What it can't have is additional instance fields.

Key Points: • A compact constructor has no parameter list. It runs before the fields are assigned, so you validate or adjust the parameters, and the compiler assigns them afterwards. • Any extra constructor must call the canonical constructor with this(...). • Instance methods can compute values from the components, such as fullName() or isAdult(). • You can override generated methods such as toString() or an accessor, for example to mask a password. • Defensive copies (List.copyOf()) in the compact constructor make list components truly immutable.

Code Example:

import java.util.List;

public class RecordValidation {

    record Account(String id, double balance, List<String> owners) {

        Account {                                        // compact constructor
            if (balance < 0) throw new IllegalArgumentException("balance < 0");
            id = id.trim().toUpperCase();                // normalise
            owners = List.copyOf(owners);                // defensive copy
        }

        Account(String id) {                             // extra constructor
            this(id, 0, List.of());
        }

        boolean isEmpty() { return balance == 0; }

        static Account of(String id, double balance) {   // static factory
            return new Account(id, balance, List.of("primary"));
        }
    }

    public static void main(String[] args) {
        System.out.println(Account.of("  acc-1 ", 500));
        System.out.println(new Account("acc-2").isEmpty());
        try {
            new Account("acc-3", -10, List.of());
        } catch (IllegalArgumentException ex) {
            System.out.println("Rejected: " + ex.getMessage());
        }
    }
}

Output:

Account[id=ACC-1, balance=500.0, owners=[primary]] true Rejected: balance < 0

Good to Know: Point out that validating in the compact constructor means an invalid record can never exist anywhere in the application. That is a strong argument for records as value objects in domain code.

Interview Tip: A concise interview answer is:

"Yes. A compact constructor lets me validate or normalise the components before they're assigned, I can add extra constructors that call the canonical one, and I can add instance and static methods. The only thing I can't add is extra instance fields."

Previous question: What are records in Java, and when should you use them?

Next question: What is the difference between a record, a regular class and a Lombok @Data class?

More Java 17 and 21 Features interview questions

All Java 17 and 21 Features questions