1. Inicialización de doble llave
La inicialización mediante llaves dobles (
en lo sucesivo, inicialización con llaves dobles ) es una herramienta Java para crear colecciones como listas, conjuntos y mapas simultáneamente con su declaración.
Cuando necesita listas con elementos fijos, como una lista de productos o monedas admitidos, declarar la lista al mismo tiempo que la inicializa mejora la legibilidad del código. Es por eso que la inicialización con doble llave está ganando popularidad, ya que no existen otros métodos estándar para crear colecciones con inicialización simultánea en el código. Desafortunadamente, a diferencia de otros lenguajes de programación, Java no admite colecciones de literales. Debido a esta limitación, crear una Lista no modificable incluso
con una pequeña cantidad de elementos nos obliga a escribir muchas líneas de código en forma de llamadas repetidas
add()
para agregar los elementos deseados con ajuste final:
List<Integer> list = new ArrayList<>();
list.add(2);
list.add(3);
list.add(5);
list.add(7);
List<Integer> unmodifiableList = Collections.unmodifiableList(list);
Esta es una descripción innecesariamente redundante que podría simplificarse. Completemos listas estáticas de la manera que más nos convenga, es decir, directamente en bloques estáticos durante la inicialización, que es en lo que
Double brace
nos ayudará la inicialización, permitiéndonos escribir todo en una línea:
List<Integer> list = Collections.unmodifiableList(new ArrayList<Integer>() {{
add(2);
add(3);
add(5);
}});
De manera similar,
Double brace
la inicialización nos ayudará a completar valores y
HashMap
:
Map<Integer, String> intToString = new HashMap<Integer, String>(){{
put(1, "one");
put(2, "two");
put(3, "three");
}};
Todo parece muy elegante, pero tiene sus inconvenientes, que hacen que la inicialización de doble llave sea un antipatrón. Los veremos más a fondo en el próximo capítulo.
Pros y contras de la inicialización de doble llave.
Double
La inicialización de llaves utiliza la creación de una clase
interna anónima . Lo que inicialmente está oculto en la superficie, sin embargo,
Double brace
la inicialización crea una clase con una mayor inicialización de su instancia cada vez que la usa. Además se utiliza una referencia oculta a esta clase privada, lo que nos puede llevar a posibles pérdidas de memoria. Tampoco puedes usar el operador fantasma para genéricos (operador diamante < >), ya que no podemos acceder al interior de una clase anónima.
(Del traductor: Una vez más con más detalle:
después del primero { , se crea una clase anónima interna, después del segundo, { la inicialización ocurre al crear una instancia de la clase, en la que tenemos acceso a los campos y métodos del externo ( relativo a la clase anónima). |
Ventajas:
- Reducir líneas en el código
- Creación e inicialización en una sola expresión.
Desventajas:
- Creando una clase anónima oculta para ti.
- Lo cual nos cuesta costos adicionales por su instancia cada vez que la utilizamos.
- Cada vez que se crea una referencia oculta, lo que puede provocar pérdidas de memoria.
Veredicto: Debido a las desventajas anteriores y a la existencia de alternativas a la doble llave, la inicialización se considera un antipatrón en el mundo Java.
Alternativas a la inicialización de doble llave en Java
La buena noticia es que existen otras formas de lograr los mismos objetivos en Java. Podemos implementar en una línea de código la creación e inicialización de un ArrayList usando el constructor Copy de la clase Collection como se muestra a continuación:
List<Integer> list = Collections.unmodifiableList(new ArrayList<>(Arrays.asList(2, 3, 5)));
Arrays.asList()
nos devolverá una lista de longitud fija pasada al
ArrayList
constructor de la copia. Tenga en cuenta la diferencia entre las listas de longitud fija devueltas por
Arrays.asList()
y
Collections.unmodifiableList()
: no puede agregar ni eliminar elementos
ArrayList
de -, pero puede cambiar un elemento por índice usando
set()
, lo que no puede hacer con una lista devuelta por
Collections.unmodifiableList()
. Si quieres obtener una lista pequeña, esta es la mejor manera, aunque será menos transparente para
Set
otras colecciones, por lo que tendrás que crearla
List
antes de crear
Set
-a. Pero esto sigue siendo mejor que la inicialización con doble llave, ya que en este caso no se crea una clase anónima interna adicional cada vez que se utiliza. Si estás ejecutando Java 8 tienes otro método alternativo. La API JDK 8 Stream le ayudará a crear pequeñas colecciones combinando
Stream Factory
métodos de salida en una colección
List
:
List<String> list = Collections.unmodifiableList(Stream.of("abc", "bcd", "cde").collect(toList()));
En
Set
su lugar, puede utilizar
Collectors.toSet()
el método
Collectors.toList()
que se muestra a continuación:
Set<String> set = Collections.unmodifiableSet(Stream.of("abc", "bcd", "cde").collect(toSet()));
Por cierto,
Stream collect
los métodos no garantizan que las colecciones que generan estén protegidas contra cambios. En Java 8, las colecciones que devolvieron (como -
ArrayList
,
HashSet
y
HashMap
) son bastante comunes (podemos cambiarlas), pero este hecho puede corregirse en futuras versiones de JDK. Eso es todo por ahora sobre
Double brace
la inicialización en Java. Esta plantilla es aceptable para pruebas y demostraciones, pero no lo suficientemente buena para uso en producción. Debido a sus desventajas inherentes, la inicialización de doble llave se ha convertido en un antipatrón en estos días, especialmente dadas las alternativas disponibles. Yo mismo todavía uso esta construcción para inicializar mapas estáticos y eso es todo. Porque
List
prefiero crear
Collections
combinando con crear
Array.asList
en su constructor. Y si uso Java 8, un diseño que utiliza Stream API y
collect()
.
Artículos relacionados: si disfrutó de este tutorial y desea obtener más información sobre los patrones, principios y mejores prácticas de programación de Java, es posible que también desee consultar los otros artículos de nuestro
sitio .
Lectura recomendada: si desea obtener más información sobre patrones y mejores prácticas, debe leer
Programación efectiva de Joshua Bloch , ningún libro puede reemplazarlo. Y si ya domina Java y está buscando un libro sobre patrones de diseño, cuyo estilo de presentación humorístico sea interesante y fácil de leer, preste atención a
“Head First”. Patrones de diseño" .
Del traductor: Proporcioné deliberadamente un enlace al libro original de Bloch, ya que su traducción al ruso no tuvo éxito (por ejemplo, Builder = constructor). |
Traducción del artículo ¿Qué es la inicialización de doble llave en Java? Ejemplo antipatrón (publicado en octubre de 2015).
GO TO FULL VERSION