En Java, ¿por qué es una mejor práctica declarar un registrador static final
?
private static final Logger S_LOGGER
En Java, ¿por qué es una mejor práctica declarar un registrador static final
?
private static final Logger S_LOGGER
Respuestas:
private
- para que ninguna otra clase pueda secuestrar tu registradorstatic
- por lo que solo hay una instancia de registrador por clase, evitando también los intentos de serializar registradoresfinal
- no es necesario cambiar el registrador durante la vida útil de la claseAdemás, prefiero que el nombre log
sea lo más simple posible, pero descriptivo.
EDITAR: Sin embargo, hay una excepción interesante a estas reglas:
protected final Logger log = LoggerFactory.getLogger(getClass());
Opuesto a:
private static final Logger log = LoggerFactory.getLogger(Foo.class);
La primera forma le permite usar el mismo nombre de registrador (nombre de la clase real) en todas las clases en toda la jerarquía de herencia. Entonces, si se Bar
extiende Foo
, ambos iniciarán sesión en el Bar
registrador. Algunos lo encuentran más intuitivo.
log
nombre más fácil de escribir y más agradable de leer que dispersar el código LOG
. Solo es cuestión de dev. acuerdo de equipo
Consulte esta publicación de blog: Deshágase de los registradores estáticos de Java . Así es como usas slf4j con jcabi-log :
import com.jcabi.log.Logger;
class Foo {
void save(File f) {
Logger.info(this, "file %s saved successfully", f);
}
}
Y nunca más uses ese ruido estático.
static
significa que solo crea un registrador por clase, no un registrador por instancia de su clase. En general, esto es lo que desea, ya que los registradores tienden a variar únicamente según la clase.
final
significa que no vas a cambiar el valor de la logger
variable. Lo cual es cierto, ya que casi siempre arroja todos los mensajes de registro (de una clase) al mismo registrador. Incluso en las raras ocasiones en que una clase quiera enviar algunos mensajes a un registrador diferente, sería mucho más claro crear otra variable de registrador (por ejemplo widgetDetailLogger
) en lugar de mutar el valor de una variable estática sobre la marcha.
¿Cuándo quieres cambiar el valor del campo?
Si nunca va a cambiar el valor, hacer que el campo sea final hace obvio que nunca cambiará el valor.
Normalmente, inicializa el registrador para iniciar sesión utilizando el nombre de la clase, lo que significa que si no fuera estático, terminaría con cada instancia de la clase teniendo una instancia de él (huella de memoria alta), pero todos estos registradores lo harían comparte la misma configuración y se comporta exactamente igual. Esa es la razón detrás de la static
parte. Además, debido a que cada uno Logger
se inicializa con el nombre de la clase, para evitar conflictos con las subclases, usted lo declara private
para que no se pueda heredar. Definal
viene del punto en que normalmente no cambia Logger
durante la ejecución, por lo que una vez inicializado nunca lo "reconfigura", en cuyo caso tiene sentido hacerlo final para asegurarse de que nadie pueda cambiarlo (por error o de otra manera). Por supuesto si vas a usar unLogger
de una manera diferente, es posible que NO necesite usar static final
, pero me aventuraría a adivinar que el 80% de las aplicaciones usarían el registro como se explicó anteriormente.
Para responder a esa pregunta, debería haberse preguntado para qué sirven "estático" y "final".
Para un Logger, (supongo que habla de la clase Log4J Logger) desea una categoría por clase. Lo que debería llevar al hecho de que lo asigna solo una vez, y no hay necesidad de más de una instancia por clase. Y presumiblemente no hay razón para exponer el objeto Logger de una clase a otra, entonces, ¿por qué no hacerlo privado y seguir algunos Principios OO?
También debe tener en cuenta que el compilador puede aprovechar eso. Entonces su código funciona un poco mejor :)
Porque ese suele ser el tipo de funcionalidad que se puede compartir en todas las instancias de sus objetos. No tiene mucho sentido (90% del tiempo) tener un registrador diferente para dos instancias de la misma clase.
Sin embargo, también puede ver a veces las clases de registrador declaradas como singletons o incluso simplemente ofreciendo funciones estáticas para registrar sus cosas.
Este código es vulnerable, pero, después de Java7, podemos usarlo en Logger lgr = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
lugar del registrador estático.
This is code is vulnerable
¿Podría aclarar que responde un poco?
Idealmente, Logger debería ser el siguiente hasta Java 7, para no dar Sonar y dar un Código de cumplimiento: privado: nunca estará accesible fuera de su clase padre. Si otra clase necesita registrar algo, debe crear una instancia de su propio registrador. static: no dependerá de una instancia de una clase (un objeto). Al registrar algo, por supuesto, se puede proporcionar información contextual en los mensajes, pero el registrador debe crearse a nivel de clase para evitar crear un registrador junto con cada objeto y, por lo tanto, evitar la huella de memoria alta. final: se creará una vez y solo una vez por clase.
Además de las razones dadas en las otras respuestas, una cosa con la que me topé fue que si mi registrador no era estático ni final:
...
public Logger logger = LoggerFactory.getLogger(DataSummary.class);
public String toJson() {
GsonBuilder gsonBuilder = new GsonBuilder();
return gsonBuilder.create().toJsonTree(this).toString();
}
...
en ciertos casos (cuando estaba usando la biblioteca Gson) obtendría una excepción stackoverflow. Mi situación específica fue crear una instancia de la clase que contiene el registrador no estático no final. Luego llame al método toJson que invocó a GsonBuilder:
...
DataSummary ds = new DataSummary(data);
System.out.println(ds.toJson());
...
En realidad, los registradores estáticos pueden ser "dañinos" ya que se supone que funcionan en un contexto estático. Al tener un entorno dinámico, por ejemplo. OSGi podría ayudar el uso de registradores no estáticos. Como algunas implementaciones de registro hacen un almacenamiento en caché de los registradores internamente (AFAIK al menos log4j), el impacto en el rendimiento puede ser insignificante.
Un inconveniente de los registradores estáticos es, por ejemplo. recolección de basura (cuando una clase se usa solo una vez, por ejemplo, durante la inicialización, el registrador se mantendrá).
Para más detalles consultar:
Ver también:
Según la información que leí en Internet sobre cómo hacer que el registrador sea estático o no, la mejor práctica es usarlo de acuerdo con los casos de uso.
Hay dos argumentos principales:
1) Cuando lo hace estático, no se recolecta basura (uso de memoria y rendimiento).
2) Cuando no lo hace estático, se crea para cada instancia de clase (uso de memoria)
Por lo tanto, cuando crea un registrador para un singleton, no necesita hacerlo estático. Porque solo habrá una instancia, por lo tanto, un registrador.
Por otro lado, si está creando un registrador para un modelo o clase de entidad, debe hacerlo estático para no crear registradores duplicados.