significa que programación programacion objetos mutables mutabilidad inmutables inmutable inmutabilidad funcional ejemplos clases java immutability

java - que - programación funcional inmutable



Ejemplos de clases inmutables (10)

Algunas clases inmutables famosas en la API estándar:

  • java.lang.String (ya mencionado)
  • Las clases contenedoras para los tipos primitivos: java.lang.Integer, java.lang.Byte, java.lang.Character, java.lang.Short, java.lang.Boolean, java.lang.Long, java.lang.Double, java.lang.Float
  • java.lang.StackTraceElement (utilizado en la construcción de stacktraces de excepción)
  • La mayoría de las clases enum son inmutables, pero esto de hecho depende del caso concreto. (No implemente enums mutables, esto lo arruinará cuando lo haga). Creo que al menos todas las clases enumeradas en la API estándar son, de hecho, inmutables.

  • java.math.BigInteger y java.math.BigDecimal (al menos los objetos de esas clases en sí, las subclases pueden introducir mutabilidad, aunque esta no es una buena idea)

  • java.io.File. Tenga en cuenta que esto representa un objeto externo a la VM (un archivo en el sistema local), que puede existir o no, y tiene algunos métodos para modificar y consultar el estado de este objeto externo. Pero el objeto File en sí permanece inmutable. (Todas las otras clases en java.io son mutables)

  • java.awt.Font: representa una fuente para dibujar texto en la pantalla (puede haber algunas subclases mutables, pero esto no sería útil)

  • java.awt.BasicStroke - un objeto auxiliar para dibujar líneas en contextos gráficos
  • java.awt.Color - (al menos los objetos de esta clase, algunas subclases pueden ser mutables o dependiendo de algunos factores externos (como los colores del sistema)), y la mayoría de las otras implementaciones de java.awt.Paint como
    • java.awt.GradientPaint,
    • java.awt.LinearGradientPaint
    • java.awt.RadialGradientPaint,
    • (No estoy seguro acerca de java.awt.TexturePaint)
  • java.awt.Cursor: representa el mapa de bits para el cursor del mouse (también aquí, algunas subclases pueden ser mutables o depender de factores externos)

  • java.util.Locale: representa una región geográfica, política o cultural específica .

  • java.utiliránID: un identificador global único en la medida de lo posible
  • aunque la mayoría de las colecciones son mutables, existen algunos métodos de envoltura en la clase java.util.Collections, que devuelven una vista no modificable en una colección. Si les pasas una colección que no se conoce en ninguna parte, estas son colecciones inmutables. Además, Collections.singletonMap() , .singletonList , .singleton devuelven .singleton inmutables de un elemento, y también hay vacíos inmutables.

  • java.net.URL y java.net.URI: representa un recurso (en Internet o en otro lugar)

  • java.net.Inet4Address y java.net.Inet6Address, java.net.InetSocketAddress
  • la mayoría de las subclases de java.security.Permission (que representan los permisos necesarios para alguna acción o dado a algún código), pero no java.security.PermissionCollection y subclases.
  • Todas las clases de java.time excepto DateTimeException son inmutables. La mayoría de las clases de los subpaquetes de java.time son inmutables también.

Uno podría decir que los tipos primitivos también son inmutables; no se puede cambiar el valor de 42, ¿o sí?

es Class AccessControlContext una clase inmutable

AccessControlContext no tiene ningún método de mutación. Y su estado consiste en una lista de ProtectionDomains (que es una clase inmutable) y un DomainCombiner. DomainCombiner es una interfaz, por lo que, en principio, la implementación podría hacer algo diferente en cada llamada.

De hecho, también el comportamiento de ProtectionDomain podría depender de la política actual en vigor; es discutible si llamar a dicho objeto inmutable.

y AccessController?

No hay objetos de tipo AccessController, ya que esta es una clase final sin un constructor accesible. Todos los métodos son estáticos. Se podría decir que AccessController no es mutable ni inmutable, o ambos.

Lo mismo es válido para todas las demás clases que no pueden tener objetos (instancias), la más famosa:

  • java.lang.Void
  • java.lang.System (pero esto tiene algún estado estático mutable - in , out , err )
  • java.lang.Math (esto también - el generador de números aleatorios)
  • java.lang.reflect.Array
  • java.util.Collections
  • java.util.Arrays

Ya conozco la definición de clases inmutables, pero necesito algunos ejemplos.


Es importante tener en cuenta que declarar una clase como final no significa que sea "inmutable", esto básicamente significa que esta clase no se puede extender (o especializar).

Las clases inmutables deben tener campos privados y finales (sin setters), por lo tanto, después de su construcción, no pueden cambiar sus valores de campo.


La clase inmutable es una clase que una vez creada, su contenido no se puede cambiar. Los objetos inmutables son los objetos cuyo estado no se puede cambiar una vez construido. Ejemplo- Cadena y todas las clases de java wrapper.

Los objetos mutables son los objetos cuyo estado se puede cambiar una vez construidos. Ejemplo: StringBuffer Una vez que el valor ha cambiado la ubicación de la memoria se altera. Vea el ejemplo a continuación -

public static void immutableOperation(){ String str=new String("String is immutable class in Java object value cann''t alter once created..."); System.out.println(str); str.replaceAll("String", "StringBuffer"); System.out.println(str); str.concat("Concating value "); System.out.println(str + "HashCode Value " + str.hashCode()); str=str.concat("Concating value "); System.out.println(str + "HashCode Val " + str.hashCode()); } public static void mutableOperation(){ StringBuffer str=new StringBuffer("StringBuffer is mutable class in Java object value can alter once created..."); System.out.println(str + "HashCode Val - " + str.hashCode()); str.replace(0, 12, "String"); System.out.println(str + "HashCode Val - " + str.hashCode()); }


La documentación de Sun (Oracle) tiene una excelente lista de verificación sobre cómo hacer un objeto inmutable.

  1. No proporcione métodos "setter": métodos que modifican campos u objetos a los que se hace referencia por campos.
  2. Haga todos los campos finales y privados.
  3. No permita que las subclases anulen los métodos. La forma más sencilla de hacerlo es declarar la clase como definitiva. Un enfoque más sofisticado es hacer que el constructor sea privado y construir instancias en métodos de fábrica.
  4. Si los campos de la instancia incluyen referencias a objetos mutables, no permita que esos objetos sean cambiados:
    • No proporcione métodos que modifiquen los objetos mutables.
    • No comparta referencias a los objetos mutables. Nunca almacene referencias a objetos externos y mutables pasados ​​al constructor; si es necesario, cree copias y almacene referencias a las copias. De forma similar, cree copias de sus objetos mutables internos cuando sea necesario para evitar devolver los originales en sus métodos.

De: http://download.oracle.com/javase/tutorial/essential/concurrency/imstrat.html

El sitio también proporciona ejemplos de su uso en un contexto de concurrencia, pero la inmutabilidad también es útil al escribir bibliotecas. Asegura que las personas que llaman a la biblioteca solo puedan cambiar lo que les permitimos.


Las clases inmutables no se pueden cambiar después de la construcción. Entonces, por ejemplo, Java String es inmutable.

Para hacer que una clase sea inmutable, debes hacerla final y todos los campos private y final . Por ejemplo, la siguiente clase es inmutable:

public final class Person { private final String name; private final int age; private final Collection<String> friends; public Person(String name, int age, Collection<String> friends) { this.name = name; this.age = age; this.friends = new ArrayList(friends); } public String getName() { return this.name; } public int getAge() { return this.age; } public Collection<String> getFriends() { return Collections.unmodifiableCollection(this.friends); } }

He agregado un método en el ejemplo de código que muestra cómo manejar colecciones, un punto importante.

Siempre que sea posible , conviene que las clases sean inmutables, porque entonces no tiene que preocuparse por cosas como la seguridad de los hilos.


Me gusta usar ejemplos que tengan una propiedad mutable. Esto ayuda a entender cómo las clases inmutables realmente funcionan.

Clase mutable

class MutableBook { private String title; public String getTitle(){ return this.title; } public void setTitle(String title){ this.title = title; } }

Y una implementación inmutable utilizando la instancia mutable de un libro.

public class ImmutableReader { private final MutableBook readersBook; private final int page; public ImmutableReader(MutableBook book) { this(book, 0); } private ImmutableReader(MutableBook book, int page){ this.page = page; // Make copy to ensure this books state won''t change. MutableBook bookCopy = new MutableBook(); bookCopy.setTitle(book.getTitle()); this.readersBook = bookCopy; } public MutableBook getBook() { // Do not return the book, but a new copy. Do not want the readers // book to change it''s state if developer changes book after this call. MutableBook bookCopy = new MutableBook(); bookCopy.setTitle(this.readersBook.getTitle()); return bookCopy; } public int getPage() { // primitives are already immutable. return page; } /** * Must return reader instance since it''s state has changed. **/ public ImmutableReader turnPage() { return new ImmutableReader(this.readersBook, page + 1); } }

Para que tu clase sea verdaderamente inmutable, debe cumplir con la siguiente cirteria:

  • Todos los miembros de la clase son declarados definitivos.
  • Todas las variables utilizadas en una clase en el nivel de clase deben ser instanciadas cuando se construye la clase.
  • Ninguna variable de clase puede tener un método setter.
    • Esto está implícito en la primera declaración, pero quiero dejar en claro que no se puede cambiar el estado de la clase.
  • Todos los objetos secundarios también deben ser inmutables, o su estado nunca cambió en la clase inmutable.
    • Si tiene una clase con propiedades mutables, debe bloquearla. Declare que es privado y asegúrese de que nunca cambie su estado.

Para aprender un poco más echa un vistazo a mi publicación en el blog: http://keaplogik.blogspot.com/2015/07/java-immutable-classes-simplified.html


Para crear una clase inmutable, debe seguir los siguientes pasos:

  1. Declare la clase como final para que no pueda extenderse.
  2. Haga que todos los campos sean privados para que no se permita el acceso directo.
  3. No proporcione métodos setter para variables
  4. Haga que todos los campos mutables sean definitivos para que su valor se pueda asignar solo una vez.
  5. Inicialice todos los campos mediante un constructor que realice una copia en profundidad.
  6. Realice la clonación de objetos en los métodos captadores para devolver una copia en lugar de devolver la referencia real del objeto.

Un ejemplo se puede encontrar here .

También podemos usar el patrón de construcción para crear fácilmente clases inmutables, un ejemplo se puede encontrar here .


Una clase inmutable simple:

public final class ImmutableStudent { private final int id; private final String name; public ImmutableStudent(int id, String name) { this.name = name; this.id = id; } public int getId() { return id; } public String getName() { return name; } }

Una clase inmutable con campos mutables:

package com.programmer.gate.beans; public final class ImmutableStudent { private final int id; private final String name; private final Age age; public ImmutableStudent(int id, String name, Age age) { this.name = name; this.id = id; Age cloneAge = new Age(); cloneAge.setDay(age.getDay()); cloneAge.setMonth(age.getMonth()); cloneAge.setYear(age.getYear()); this.age = cloneAge; } public int getId() { return id; } public String getName() { return name; } public Age getAge() { Age cloneAge = new Age(); cloneAge.setDay(this.age.getDay()); cloneAge.setMonth(this.age.getMonth()); cloneAge.setYear(this.age.getYear()); return cloneAge; } }

Referencia: Cómo crear una clase inmutable en java


String es un buen ejemplo del "mundo real" de una clase inmutable. Y puede contrastarlo con la clase mutable StringBuilder .

La mayoría de las clases de Java utilizadas para la reflexión son inmutables. Y algunos de los otros son "casi inmutables": por ejemplo, las clases que implementan Accessible tienen solo un método setAccessible que cambia el estado de la instancia Accessible .

Estoy seguro de que hay muchas más en las bibliotecas de clases estándar.


Las clases LocalDate , LocalTime y LocalDateTime (desde 1.8) también son inmutables. De hecho, este mismo tema está en el examen OCAJSE8 (1Z0-808), y es precisamente por eso que decidí tratarlo no como un simple comentario.

Todas las clases de envoltura primitiva (como Boolean , Character , Byte , Short , Integer , Long , Float y Double ) son inmutables.

Money and Currency API (programado para Java9) también debe ser inmutable.

Por cierto, las listas respaldadas por matriz (creadas por Arrays.asList(myArray) ) son estructuralmente modificables.

Además, hay algunos casos borderline como java.util.Optional (presentado en el examen OCP, 1Z0-809), que es inmutable si el elemento contenido es inmutable.