DEV Community

Cover image for Setters en un Record en Java
Jordi Ayala
Jordi Ayala

Posted on • Originally published at asjordi.dev

Setters en un Record en Java

Un record es una estructura que se caracteriza por ser inmutable, es decir, una vez que se ha creado un objeto de tipo record, no se pueden modificar sus atributos, es lo equivalente a lo que otros lenguajes de programación denominan data-class o DTO (Data Transfer Object). Sin embargo, si se requiere modificar algún atributo mediante un método setter y considerando que cada atributo dentro del record es de tipo final, ¿cómo se puede lograr esto?

Para mostrar si esto es posible, vamos a crear un record Product que tiene dos atributos name y price, y los respectivos métodos que se crean automáticamente al definir un record en Java:

public record Product(String name, double price) { }
Enter fullscreen mode Exit fullscreen mode

Ahora, si se crea un objeto de tipo Product y se intenta modificar el atributo name, se puede observar que no es posible, y ni siquiera existe un método setter para hacerlo:

Product p = new Product("Bread", 1.0);
p.setName("Water"); // Error: cannot resolve method 'setName' in 'Product'
Enter fullscreen mode Exit fullscreen mode

Pero, si sabemos que un record puede tener métodos adicionales, entonces se puede crear un método setName(String name) que modifique el atributo name y le asigne el nuevo valor, pues la respuesta es que no, no funciona como lo haría en una clase normal, por ejemplo:

public record Product(String name, double price) {
    // Error: cannot asign a value to final variable 'name'
    public void setName(String name) {
        this.name = name;
    }
}
Enter fullscreen mode Exit fullscreen mode

Entonces, ¿cómo se puede modificar un atributo de un record en Java? La respuesta es que se puede si el método set devuelve una nueva instancia del record con cada uno de sus atributos y obviamente con el o los atributos modificados. Este proceso puede ser un poco tedioso dependiendo del número de atributos que tenga el record.

public record Product(String name, double price) {

    public Product setName(String name) {
        return new Product(name, this.price);
    }

    public Product setPrice(double price) {
        return new Product(this.name, price);
    }

}
Enter fullscreen mode Exit fullscreen mode

De esta manera al invocar cualquiera de los métodos setter se obtendrá una nueva instancia del tipo Product con el atributo modificado, por ejemplo:

Product p = new Product("Bread", 1.0);
Product q = p.setName("Milk");
Product r = q.setPrice(2.0);
Enter fullscreen mode Exit fullscreen mode

Para cada objeto p, q y r se pueden invocar de forma normal sus métodos get, equals, hashCode y toString, considerando que ninguno de los objetos es igual a otro, ya que cada uno tiene un valor diferente en sus atributos.

public class Main {
    public static void main(String[] args) {
        Product p = new Product("Bread", 1.0);
        Product q = p.setName("Milk");
        Product r = q.setPrice(2.0);

        System.out.println(p); // Product[name=Bread, price=1.0]
        System.out.println(q); // Product[name=Milk, price=1.0]
        System.out.println(r); // Product[name=Milk, price=2.0]

        System.out.println(p.equals(q)); // false
        System.out.println(q.equals(r)); // false
        System.out.println(r.equals(p)); // false
    }
}
Enter fullscreen mode Exit fullscreen mode

En este punto, es importante considerar si este enfoque es el adecuado para el problema que se está resolviendo, considerando que un record está diseñado para ser una estructura que permite almacenar y transportar información de una manera simple dentro de una aplicación y ser inmutable, o sí se requiere de una estructura con mayor flexibilidad, entonces se debería utilizar una clase. Para mayor información sobre cuándo utilizar un record o una clase, se puede consultar el siguiente post.

Billboard image

Synthetic monitoring. Built for developers.

Join Vercel, Render, and thousands of other teams that trust Checkly to streamline monitor creation and configuration with Monitoring as Code.

Start Monitoring

Top comments (0)

The Most Contextual AI Development Assistant

Pieces.app image

Our centralized storage agent works on-device, unifying various developer tools to proactively capture and enrich useful materials, streamline collaboration, and solve complex problems through a contextual understanding of your unique workflow.

👥 Ideal for solo developers, teams, and cross-company projects

Learn more

👋 Kindness is contagious

Discover a treasure trove of wisdom within this insightful piece, highly respected in the nurturing DEV Community enviroment. Developers, whether novice or expert, are encouraged to participate and add to our shared knowledge basin.

A simple "thank you" can illuminate someone's day. Express your appreciation in the comments section!

On DEV, sharing ideas smoothens our journey and strengthens our community ties. Learn something useful? Offering a quick thanks to the author is deeply appreciated.

Okay