Clase inmutable en Java - Conceptos de codificación N

En este tutorial, descubriremos clase inmutable y sus ventajas en seguridad de subprocesos, almacenamiento en caché y colecciones. También veremos las reglas para crear clases inmutables y posiblemente escribiremos un clase inmutable desde cero en Java.

Índice
  1. ¿Qué es una clase inmutable?
  2. Ventajas de la clase inmutable
  3. ¿Cómo crear una clase inmutable?
  4. Resumen

¿Qué es una clase inmutable?

clase inmutable significa que una vez que objeto se inicializa desde este Clasificarno podemos modificar el estado de este objeto.

En otras palabras, un objeto inmutable no se puede modificar después de crearlo. Cuando se necesita un nuevo valor, la práctica aceptada es hacer una copia del objeto que tiene el nuevo valor.

Ejemplos

En Java, todas las clases contenedoras primitivas (Entero, Byte, Largo, Flotante, Doble, Carácter, Booleano y Corto) y cadena de caracteres son de naturaleza inmutable.

String es la clase inmutable más conocida entre los desarrolladores. El objeto String no se puede modificar una vez inicializado. Operaciones como adornar(), subcadena(), reemplazar(), aMayúsculas(), aLowerCase() siempre devuelve una nueva instancia y no afecta a la instancia actual.

En el siguiente ejemplo, s1.toUpperCase() devuelve una nueva instancia que debe reasignarse a s1, si desea que s1 se refiera a una nueva instancia en mayúsculas.

String s1 = new String("CodingNConcepts");
String s2 = s1.toUpperCase();
System.out.println(s1 == s2);  //false
s1 = s2;                       //assign back to s1
System.out.println(s1 == s2);  //true

Ventajas de la clase inmutable

Algunas de las principales ventajas de la clase inmutable son: -

1. Objeto mutable vs inmutable

A objeto editable comienza con un estado (valores iniciales de las variables de instancia). Cada mutación de la variable de instancia pone el objeto en otro estado. Esto lleva a la necesidad de documentar todos los estados posibles en los que puede estar un objeto mutable. También es difícil evitar estados incoherentes o inválidos. Por lo tanto, todo esto hace que un objeto mutable sea difícil de usar.

Mientras que, objeto inmutable tener un solo estado, que es principalmente una ventaja de la clase inmutable.

2. Seguridad de los cables

Los objetos inmutables son inherentemente seguros para subprocesos. No requieren sincronización. Dado que no hay forma de que el estado de un objeto inmutable pueda cambiar, no hay posibilidad de que un subproceso observe el efecto de otro subproceso. No tenemos que lidiar con las complejidades de compartir un objeto entre subprocesos (como bloqueo, sincronización, volatilidad variable, etc.). Así, podemos compartir libremente objetos inmutables. Esta es la forma más fácil de garantizar la seguridad de los subprocesos.

3. Reutilizable/Ocultable

Los objetos inmutables fomentan el almacenamiento en caché o el almacenamiento de instancias de uso frecuente en lugar de crear una cada vez. Esto se debe a que dos instancias inmutables con las mismas propiedades/valores son iguales.

Aquí hay algunos ejemplos de aplicación: -

Clases contenedoras primitivas
La creación de objetos de envoltorio primitivos (entero, flotante, doble, etc.) utilizando el método de fábrica estático valueOf no siempre devuelve nuevas instancias de envoltorio. En caso de número entero, almacenan en caché los valores enteros de -128 a 127 por defecto.

Integer oneV1 = new Integer(1);
Integer oneV2 = new Integer(1);
System.out.println(oneV1 == oneV2);       //false
System.out.println(oneV1.equals(oneV2));  //true

oneV1 = Integer.valueOf(1);               //returns cached instance
oneV2 = Integer.valueOf(1);               //returns cached instance
System.out.println(oneV1 == oneV2);       //true
System.out.println(oneV1.equals(oneV2));  //true

Entero grande
BigInteger almacena algunos valores comunes de BigInteger como variables de instancia.

 /**
 * The BigInteger constant zero.
 */
public static final BigInteger ZERO = new BigInteger(new int[0], 0);

Esto reduce la huella de memoria y los costos de recolección de elementos no utilizados.

4. Bloques de construcción para colecciones

Los objetos inmutables son un gran componente básico para las colecciones en comparación con los objetos mutables. Entendamos el problema al que nos enfrentamos con los objetos editables en las colecciones.

Primero, creamos un mutable La persona clasificar

class Person {
	
	String name;
	
	public String getName() {
		return name;
	}
	
	public void setName(String name) {
		this.name = name;
	}
	
	@Override
	public String toString() {
		return "Person { name: " + name + " }";
	}
}

Ahora vamos a crear objetos de persona para crear Ajustar de la gente:-

Person person1 = new Person();
person1.setName("Adam");

Person person2 = new Person();
person2.setName("Ben");

Set<Person> setOfPerson = new HashSet<>(Arrays.asList(person1, person2));
System.out.println(setOfPerson);

person1.setName("Charlie");
System.out.println(setOfPerson);

Output

[Person { name: Adam }, Person { name: Ben }] [Person { name: Charlie }, Person { name: Ben }]

Queríamos crear un conjunto de personas Adán y Bien pero la siguiente parte del código mutó el Adán para Charly que no se espera. Resolveremos este problema creando una clase inmutable Persona inmutable más adelante en el artículo.

Como hemos visto que los objetos mutables se pueden mutar incluso si no lo son, los objetos inmutables están bien para ser usados ​​como Claves del mapadentro Conjunto, Listay otras colecciones.

¿Cómo crear una clase inmutable?

Para crear un clase inmutableusted debe tener en cuenta los siguientes puntos:-

  1. declararlo clase como final para que no se pueda extender y las subclases no puedan anular los métodos.
  2. Hazlo todo campos como privados por lo que no se permite el acceso directo
  3. Hazlo todo campos como final por lo que el valor no se puede cambiar una vez inicializado
  4. Traer sin métodos setter — los métodos setter son métodos que modifican campos u objetos a los que hacen referencia los campos.
  5. Inicializar todos los campos finales a través de un constructor y haga una copia completa para objetos editables.
  6. Si la clase contiene un objeto mutable:
    • No proporcione ningún método que modifique objetos mutables.
    • Siempre devuelve una copia del objeto mutable de metodo captador y nunca devuelve la referencia del objeto real.

Apliquemos todos los puntos anteriores y creemos nuestra clase inmutable Persona inmutable

ImmutablePerson.java
/**
 * Immutable class should mark as final so it can not be extended. 
 * Fields should mark as private so direct access is not allowed.
 * Fields should mark as final so value can not be modified once initialized.
 **/
public final class ImmutablePerson {

    // String - immutable
    private final String name;
    
    // Integer - immutable
    private final Integer weight;
    
    // Date - mutable
    private final Date dateOfBirth;
    
    /**
     * All the final fields are initialized through constructor
     * Perform a deep copy of immutable objects
     */
    public ImmutablePerson(String name, Integer weight, Date dateOfBirth){
        this.name = name;
        this.weight = weight;
        this.dateOfBirth = new Date(dateOfBirth.getTime());
    }
    
    /**********************************************
     ***********PROVIDE NO SETTER METHODS *********
     **********************************************/
    
    /**
     * String class is immutable so we can return the instance variable as it is
     **/
    public String getName() {
        return name;
    }
    
    /**
     * Integer class is immutable so we can return the instance variable as it is
     **/
    public Integer getWeight() {
        return weight;
    }
    
    /**
     * Date class is mutable so we need a little care here.
     * We should not return the reference of original instance variable.
     * Instead a new Date object, with content copied to it, should be returned.
     **/
    public Date getDateOfBirth() {
        return new Date(dateOfBirth.getTime());
    }
    
    @Override
    public String toString() {
    	return "Person { name: " + name + ", weight: " + weight + ", dateOfBirth: " + new SimpleDateFormat("dd-MM-yyyy").format(dateOfBirth) + "}";
    }
}

Ahora vamos a crear objetos de persona inmutables para crear Ajustar de la gente:-

ImmutablePerson person1 = new ImmutablePerson("Adam", 55, new SimpleDateFormat("dd-MM-yyyy").parse("01-01-2001"));

ImmutablePerson person2 = new ImmutablePerson("Ben", 50, new SimpleDateFormat("dd-MM-yyyy").parse("02-02-2002"));

Set<ImmutablePerson> setOfPerson = new HashSet<>(Arrays.asList(person1, person2));
System.out.println(setOfPerson);
/**
* ImmutablePerson do not provide setter methods, 
* no way to mutate name, weight, or date property fields.
*/
//person1.setName("Charlie");
//person1.setWeight(90);
//person1.setDate(new SimpleDateFormat("dd-MM-yyyy").parse("03-03-2003"));

/**
* getDateOfBirth() method returns new instance of date, 
* setYear() will not change value of person1's date field.
*/
Date person1Date = person1.getDateOfBirth();
person1Date.setYear(2020);
System.out.println(setOfPerson);

Output

[Person { name: Adam, weight: 55, dateOfBirth: 01-01-2001}, Person { name: Ben, weight: 50, dateOfBirth: 02-02-2002}] [Person { name: Adam, weight: 55, dateOfBirth: 01-01-2001}, Person { name: Ben, weight: 50, dateOfBirth: 02-02-2002}]

Vemos que no podemos mutar la colección de Persona inmutable una vez creado.

Resumen

En este tutorial, descubrimos clase inmutable en Java y sus ventajas. Además, clase inmutable es una pregunta de entrevista frecuente para verificar su comprensión del patrón de diseño, los objetos inmutables y mutables y la palabra clave final.

¿Qué piensas?

Según Oracle Docs para Clases inmutables, No permita que las subclases anulen los métodos. La forma más fácil de hacer esto es declarar la clase como final. Un enfoque más sofisticado es hacer que el constructor sea privado y crear instancias en los métodos de fábrica.

Tenga en cuenta que hemos marcado la clase como final y constructor como público en nuestro Persona inmutable clasificar.

es discutible ¿Deberíamos usar un constructor privado con un método de fábrica estático para crear instancias? Mi opinión es que estamos restringiendo la creación de instancias mediante un constructor privado, que no es un escenario deseado para la inmutabilidad.

Qué piensas sobre esto ? Por favor comenta.

Las referencias:

Si quieres conocer otros artículos parecidos a Clase inmutable en Java - Conceptos de codificación N puedes visitar la categoría Tutoriales.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Subir

Esta página web utiliza cookies para analizar de forma anónima y estadística el uso que haces de la web, mejorar los contenidos y tu experiencia de navegación. Para más información accede a la Política de Cookies . Ver mas