En Java, la inmutabilidad significa que una vez que se crea un objeto, su estado interno no se puede cambiar. Las clases inmutables en Java brindan muchas ventajas, como la seguridad de los subprocesos, la fácil depuración y todo eso. En Java todos los clases contenedoras (como Integer Boolean Byte Short) y la clase String es inmutable. También podemos crear nuestra propia clase inmutable.
En este artículo vamos a aprender:
- ¿Qué significa la inmutabilidad?
- Por que es util
- Cómo crear nuestra propia clase inmutable
- Por qué es importante la copia profunda
- ¿Cuáles son las limitaciones que tienen los tipos de registros Java?
¿Qué es una clase inmutable?
Una clase inmutable es una clase cuyos objetos no se pueden cambiar una vez creados. Si hacemos alguna modificación resultará en un nuevo objeto. Este método se utiliza en aplicaciones concurrentes.
Reglas para crear una clase inmutable
- La clase debe declararse como final para que no se puedan crear clases secundarias.
- Los miembros de datos de la clase deben declararse. privado por lo que no se permite el acceso directo.
- Los miembros de datos de la clase deben declararse como final para que no podamos cambiar su valor después de la creación del objeto.
- Un constructor parametrizado debe inicializar todos los campos realizando una copia profunda para que los miembros de datos no se puedan modificar con una referencia de objeto.
- La copia profunda de objetos debe realizarse en los métodos getter para devolver una copia en lugar de devolver la referencia del objeto real.
Nota : No debería haber definidores o, en términos más simples, no debería haber ninguna opción para cambiar el valor de la variable de instancia.
Ejemplo: implementación de clase inmutable
El proceso de Android Acore sigue deteniéndose
Estudiante.java
Java// Java Program to Create An Immutable Class import java.util.HashMap; import java.util.Map; // declare the class as final final class Student { // make fields private and final private final String name; private final int regNo; private final Map<String String> metadata; // initialize all fields via constructor public Student(String name int regNo Map<String String> metadata) { this.name = name; this.regNo = regNo; // deep copy of mutable object (Map) Map<String String> tempMap = new HashMap<>(); for (Map.Entry<String String> entry : metadata.entrySet()) { tempMap.put(entry.getKey() entry.getValue()); } this.metadata = tempMap; } // only provide getters (no setters) public String getName() { return name; } public int getRegNo() { return regNo; } // return deep copy to avoid exposing internal state public Map<String String> getMetadata() { Map<String String> tempMap = new HashMap<>(); for (Map.Entry<String String> entry : this.metadata.entrySet()) { tempMap.put(entry.getKey() entry.getValue()); } return tempMap; } }
En este ejemplo hemos creado una clase final llamada Alumno. Tiene tres miembros de datos finales, un constructor parametrizado y métodos getter. Tenga en cuenta que aquí no existe un método de establecimiento. También tenga en cuenta que no necesitamos realizar una copia profunda o clonación de miembros de datos de tipos de contenedor, ya que ya son inmutables.
Frikis.java:
Javaimport java.util.HashMap; import java.util.Map; public class Geeks { public static void main(String[] args) { // create a map and adding data Map<String String> map = new HashMap<>(); map.put('1' 'first'); map.put('2' 'second'); // create an immutable Student object Student s = new Student('GFG' 101 map); // accessing data System.out.println(s.getName()); System.out.println(s.getRegNo()); System.out.println(s.getMetadata()); // try to modify the original map map.put('3' 'third'); System.out.println(s.getMetadata()); // try to modify the map returned by getMetadata() s.getMetadata().put('4' 'fourth'); System.out.println(s.getMetadata()); } }
Incluso después de modificar el mapa original o devuelto, el estado interno del objeto Estudiante permanece sin cambios. Esto confirma el concepto de inmutabilidad.
Producción:
GFG
101
{1=first 2=second}
{1=first 2=second}
{1=first 2=second}
Limitación del registro Java con campos mutables
Java 14 introducido registro . Esta es una forma clara y concisa de definir clases similares inmutables:
registrar Estudiante (nombre de cadena int regNo Mapa
metadatos) {}
Pero esto sólo ofrece una inmutabilidad superficial. Si el Mapa se modifica externamente el estado interno del registro cambia:
Mapa
mapa = nuevo HashMap<>(); map.put('1' 'primero');
Estudiante s = nuevo Estudiante(mapa 'ABC' 101);
// Cambia el estado interno - NO seguro
map.put('2' 'segundo');
s.metadata().put('3' 'tercero');
Nota : Utilice el registro solo si todos los campos son de tipos inmutables como String int u otros registros.