Históricamente, la inicialización perezosa surgió para optimizar el uso de recursos, donde un objeto se crea solo cuando realmente se necesita. Esto fue importante inicialmente al trabajar con objetos pesados, conexiones, cachés o al implementar patrones complejos (por ejemplo, Singleton).
El problema radica en que si se crean todos los recursos de inmediato, se puede gastar memoria, tiempo y potencia innecesariamente, incluso cuando el objeto no se necesita. La inicialización perezosa resuelve la tarea de creación "retrasada".
La solución generalmente se implementa verificando: si el objeto aún no ha sido creado, lo creamos, de lo contrario, devolvemos el existente.
Ejemplo de código:
public class LazyHolder { private Resource resource; public Resource getResource() { if (resource == null) { resource = new Resource(); } return resource; } }
En condiciones multihilo, se requiere sincronización.
Aspectos clave:
¿Es el Double-Checked Locking una implementación confiable para la inicialización perezosa de Singleton?
Solo desde Java 5, ya que antes el modelo de memoria no lo garantizaba. Es necesario usar la palabra clave volatile para el campo recurso.
private volatile Resource resource; public Resource getResource() { if (resource == null) { synchronized(this) { if (resource == null) { resource = new Resource(); } } } return resource; }
¿Tiene sentido hacer inicialización perezosa para objetos livianos?
Por lo general, no. Es mejor crear objetos "livianos" desde el principio, para no reducir la legibilidad del código ni complicarlo con lógica innecesaria.
¿Funciona la inicialización perezosa en la serialización de objetos?
No siempre. En la serialización, podría recuperarse un estado "antiguo" o requerir lógica adicional en readObject().
En un servicio de alta carga, un pool especial de objetos se parseaba perezosamente, pero no estaba sincronizado. Dos hilos inicializaban el objeto simultáneamente, lo que llevaba a fugas de memoria y errores impredecibles.
Ventajas:
Desventajas:
En una gran aplicación web, la analítica se conecta solo a través de una llamada API mediante un objeto proxy inicializado perezosamente con double-checked locking.
Ventajas:
Desventajas: