Final no es inmutable. En Java, una referencia puede ser final y el objeto al que apunta seguir cambiando.
En mi día a día, veo APIs que devuelven listas mutables o exponen setters que permiten modificar el estado después de crear el objeto. Eso genera efectos colaterales difíciles de rastrear y pruebas más complicadas. Si queremos garantizar consistencia, necesitamos distinguir bien cuándo hablamos de la referencia y cuándo hablamos del estado del objeto.
El concepto en dos ideas rápidas:
- Final: bloquea la re-asignación de la referencia, no el contenido. Puedes hacer esto y, aun así, manipular el objeto si es mutable.
- Inmutable: el objeto no cambia después de su construcción. No expone mutadores y, si tiene colecciones, no las permite modificar desde fuera.
Ejemplos claros ayudan:
- Final aplicado a una colección mutable
final List<String> items = new ArrayList<>();
items.add("alpha"); // OK
// items = new ArrayList<>(); // Error: cannot assign a value to final variable
- Clase inmutable real
public final class UserId {
private final String value;
public UserId(String value) { this.value = value; }
public String value() { return value; }
}
Una clase así no expone mutadores y su estado queda fijado al construirla.
Para lograr inmutabilidad real, cuida estos puntos:
- campos privados y finales;
- no permitas setters;
- si expones datos mutables, devuelve copias defensivas o colecciones inmutables (por ejemplo, List.copyOf en Java 10+).
Hoy mismo: revisa una API que devuelve una List mutable. Ajusta para devolver una colección inmutable o una copia y añade una prueba que verifique que la lista no puede ser alterada por el consumidor. Si haces ese ajuste, ya ganamos claridad, seguridad y menos sorpresas en producción.
Top comments (0)