Significado de la nueva clase (…) {{…}} idioma de inicialización

¿Qué significa {{ ... }} bloquear en el siguiente código?

 class X { private Y var1; private X() { Z context = new Z(new SystemThreadPool()) {{ var1 = new Y(); }}; } } 

Se llama inicialización con doble llave . (EDITAR: Enlace eliminado, archivado aquí )

Significa que estás creando una subclase anónima y el código dentro de las llaves dobles es básicamente un constructor. A menudo se usa para agregar contenidos a las colecciones porque la syntax de Java para crear lo que esencialmente son constantes de colección es algo incómodo.

Entonces puedes hacer:

 List list = new ArrayList() {{ add("one"); add("two"); add("three"); }}; 

en lugar de:

 List list = new ArrayList(); list.add("one"); list.add("two"); list.add("three"); 

En realidad, no me gusta eso y prefiero hacer esto:

 List list = Arrays.asList("one", "two", "three"); 

Por lo tanto, no tiene mucho sentido en ese caso mientras que lo hace para, por ejemplo, Maps, que no tienen un ayudante conveniente.

Las llaves “externas” significan que estás haciendo una subclase anónima, las segundas llaves son el inicializador de objetos. El inicializador se ejecuta antes del constructor de la clase, pero después de cualquier super llamada (y por lo tanto también después de cualquier inicializador de superclase). También puede utilizar inicializadores en clases no anónimas, que es una forma conveniente de iniciar campos final si tiene varios constructores que no se pueden llamar entre sí, o campos que necesitan una inicialización más compleja de lo que permiten los inicializadores de campo habituales.

Considera esta clase:

 class X extends Y{ private final int lulz; private static boolean someCondition(){...} private static boolean danger() throws SomeException { ... } public X(A a) throws SomeException { super(a); lulz = someCondition()? danger() : 0; } public X(B b) throws SomeException { super(b); lulz = someCondition()? danger() : 0; } } 

Podría ser reescrito como:

 class X extends Y{ private final int lulz; private static boolean someCondition(){...} private static boolean danger() throws SomeException { ... } { // initalizer -- might throw SomeException! lulz = someCondition()? danger() : 0; } public X(A a) throws SomeException { super(a); } public X(B b) throws SomeException { super(b); } } 

Si el inicializador puede arrojar una excepción marcada, todos los constructores deben declarar que pueden lanzarla.

Estás creando una clase anónima y utilizando la clase Instance initialize r idiom, así:

 class X { private Y var1; private X() { Z context = new Z( new SystemThreadPool()) { { // This is the initialize idiom var1 = new Y(); // } // } ); // BTW you are missing ")" } } 

Como se mencionó en las respuestas anteriores, la inicialización con doble llave es correcta.

Utiliza una técnica específica para Inicializar Miembros de Instancia en Java. Es una forma abreviada de definir en una definición de clase, un bloque compartido de código que se ejecutará cuando se active cualquiera de los constructores de clase.

Estoy agregando el enlace a la documentación oficial de Java que lo describe para una visión más amplia sobre el tema.

De la documentación :

Los bloques de inicializador para las variables de instancia se parecen a los bloques de inicializador estáticos, pero sin la palabra clave estática:

{

 // whatever code is needed for initialization goes here 

}

El comstackdor de Java copia bloques de inicializador en cada constructor. Por lo tanto, este enfoque se puede usar para compartir un bloque de código entre múltiples constructores.