Java Records
Tags: java, record
Published: 2024-06-09 13:12:41

**All About Java Records :** 

**Overview :** 
Java Records, introduced in Java 14 as a preview feature and finalized in Java 16, provides a concise way to model immutable data. They simplify the boilerplate code needed for data-carrying classes by automatically generating methods like equals(), hashCode() and toString()

By the end of this post we will understand:

**What records are in Java?**
**How to create and use records in Java?**
**The benefits of using records in Java?**
**And some limitations of records in Java?**

**What are Records?**
A record in Java is a special kind of class that is designed to hold immutable data. It automatically provides implementations for methods like:

equals()
hashCode()
toString()
Getters for all fields

**Why Use Records?**
Records help reduce boilerplate code in data classes. Instead of writing constructors, getters, equals(), hashCode(), and toString() methods manually, we can define all of this with a single line of code

**How to Define a Record?** 
Here's how we can define a simple record:

```
public record Point(int x, int y) {
}

```

This single line of code automatically provides:

1. A constructor
2. Getters (x() and y())
3. equals(), hashCode(), and toString() methods

**Example: How to use Records?**
Let's see how we can use the Point record:

```
public class Main {
    public static void main(String[] args) {
        Point point = new Point(3, 4);
        
        // Using the auto-generated toString() method
        System.out.println(point);  // Output: Point[x=3, y=4]
        
        // Accessing the fields using auto-generated methods
        System.out.println("X: " + point.x());  // Output: X: 3
        System.out.println("Y: " + point.y());  // Output: Y: 4
    }
}
```

**Example: Custom Methods in Records :** 
You can also add custom methods to records:

```
public record Point(int x, int y) {
    public double distanceFromOrigin() {
        return Math.sqrt(x * x + y * y);
    }
}

public class Main {
    public static void main(String[] args) {
        Point point = new Point(3, 4);
        System.out.println("Distance from origin: " + point.distanceFromOrigin());  // Output: 5.0
    }
}
```

**Custom Constructors :**
We can also define custom constructors in records, but they must delegate to the canonical constructor:

```
public record Point(int x, int y) {
    public Point(int x) {
        this(x, 0);  // Delegating to the canonical constructor
    }
}
```

**Limitations of Records :**

**1. Immutability:** Records are immutable by design. You cannot change the values of their fields after creation.

**2. No Inheritance:** Records cannot extend other classes. They implicitly extend java.lang.Record

**3. All-Args Constructor:** We cannot create a no-argument constructor directly in records. We must always provide all the components.

**When to Use Records :** 
Use records when:

1.  We need a simple, immutable data carrier class

2.  We want to reduce boilerplate code for equals(), hashCode(), and toString() methods

3.  We don't need to extend another class or implement complex behavior
 
**Practical Example :**
Let's create a more complex example with a Person record:

```
public record Person(String name, int age) {
    public Person {
        // Custom constructor with validation
        if (age < 0) {
            throw new IllegalArgumentException("Age cannot be negative");
        }
    }
    
    // Custom method
    public String greeting() {
        return "Hello, my name is " + name + " and I am " + age + " years old.";
    }
}

public class Main {
    public static void main(String[] args) {
        Person person = new Person("Alice", 30);
        System.out.println(person.greeting());  // Output: Hello, my name is Alice and I am 30 years old.
        System.out.println(person);  // Output: Person[name=Alice, age=30]
    }
}

```
**Key Points :** 

1.  **Definition:** 
public record Person(String name, int age) {}

2.  **Custom Constructor:** 
Validates that age is non-negative

3. **Custom Method:** 
Adds a greeting() method

**Conclusion :** 
Java Records provide a simple and powerful way to create immutable data classes with minimal boilerplate code. They are especially useful for modeling data transfer objects and other simple data carriers. By understanding and using records, you can write cleaner and more concise code.

**Happy Coding...**