thread stackoverflow safe pattern examples example best java singleton

java - stackoverflow - Singleton vía enum se inicializa perezoso?



singleton example c# (2)

Este es un código singleton de enumeración muy extendido:

public enum enumClazz{ INSTANCE enumClazz(){ //do something } }

y un montón de lugares dijeron que es una inicialización perezosa. Pero estoy confundido después de leer el Capítulo 7 de '' Dentro de la máquina virtual Java '' - La vida útil de un tipo:

La especificación de la máquina virtual de Java proporciona a las implementaciones flexibilidad en el tiempo de carga y enlace de la clase y la interfaz, pero define estrictamente el tiempo de la inicialización. Todas las implementaciones deben inicializar cada clase o interfaz en su primer uso activo. Las siguientes seis situaciones califican como usos activos:

  • Se crea una nueva instancia de una clase (en bytecodes, la ejecución de una nueva instrucción. Alternativamente, a través de creación implícita, reflexión, clonación o deserialización).
  • La invocación de un método estático declarado por una clase (en bytecodes, la ejecución de una instrucción invokestatic)
  • El uso o la asignación de un campo estático declarado por una clase o interfaz, excepto los campos estáticos que son finales e inicializados por una expresión constante de tiempo de compilación (en bytecodes, la ejecución de una instrucción getstatic o putstatic)
  • La invocación de ciertos métodos reflexivos en la API de Java, como los métodos en clase Clase o en clases en el paquete java.lang.reflect
  • La inicialización de una subclase de una clase (la inicialización de una clase requiere la inicialización previa de su superclase).
  • La designación de una clase como la clase inicial (con el método main () <cuando se inicia una máquina virtual Java)

El tercer punto con estilo en negrita aclara que si el campo es static final , la inicialización del campo se realiza en tiempo de compilación. Asimismo, la INSTANCE en enumClazz es implícitamente igual a public static final y cumple con el tercer punto.

¿Puede alguien corregirme si mi entendimiento es incorrecto?


El tercer punto con estilo en negrita aclara que si el campo es ''final estático'', la inicialización del campo se realiza en el momento de la complie

No exactamente, solo se aplica a " campos estáticos que son finales e inicializados por una expresión constante de compilación ":

static final String = "abc"; //compile time constant static final Object = new Object(); //initialised at runtime

En su caso, el singleton se inicializará cuando se cargue la clase enum, es decir, la primera vez que se enumClazz referencia a enumClazz en su código.

Por lo tanto, es efectivamente perezoso, a menos que, por supuesto, tenga una declaración en algún otro lugar de su código que use la enumeración.


enum campos de instancia de enum no se "inicializan mediante una expresión constante de tiempo de compilación". No pueden ser, porque solo los tipos String y primitivos son tipos posibles para una expresión constante en tiempo de compilación .

Eso significa que la clase se inicializará cuando se acceda por primera vez a INSTANCE (que es exactamente el efecto deseado).

La excepción en el texto en negrita anterior existe, porque esas constantes (campos static final inicializados con una expresión constante de compilación) se insertarán efectivamente durante la compilación:

class A { public static final String FOO = "foo"; static { System.out.println("initializing A"); } } class B { public static void main(String[] args) { System.out.println(A.FOO); } }

La ejecución de la clase B en este ejemplo no inicializará A (y no imprimirá "inicializando A"). Y si observa el código de bytes generado para B , verá un literal de cadena con el valor "foo" y no una referencia a la clase A