Em Java, por que é uma prática recomendada declarar um criador de logs static final
?
private static final Logger S_LOGGER
Em Java, por que é uma prática recomendada declarar um criador de logs static final
?
private static final Logger S_LOGGER
Respostas:
private
- para que nenhuma outra classe possa seqüestrar seu loggerstatic
- portanto, existe apenas uma instância de logger por classe, evitando também tentativas de serializar os loggersfinal
- não é necessário alterar o logger durante a vida útil da classeAlém disso, prefiro que o nome log
seja o mais simples possível, mas descritivo.
EDIT: No entanto, há uma exceção interessante para estas regras:
protected final Logger log = LoggerFactory.getLogger(getClass());
em oposição a:
private static final Logger log = LoggerFactory.getLogger(Foo.class);
A maneira anterior permite usar o mesmo nome do criador de logs (nome da classe real) em todas as classes da hierarquia de herança. Portanto, se for Bar
estendido Foo
, ambos serão registrados no Bar
logger. Alguns acham mais intuitivo.
log
nome do que espalhar o código LOG
. Apenas uma questão de dev. acordo de equipe.
Confira esta postagem no blog: Livre-se dos Java Static Loggers . É assim que você usa o slf4j com o jcabi-log :
import com.jcabi.log.Logger;
class Foo {
void save(File f) {
Logger.info(this, "file %s saved successfully", f);
}
}
E nunca mais use esse ruído estático.
static
significa que você cria apenas um criador de logs por classe, não um criador de logs por instância da sua classe. Geralmente, é isso que você deseja - pois os registradores tendem a variar apenas com base na classe.
final
significa que você não vai alterar o valor da logger
variável. O que é verdade, já que você quase sempre lança todas as mensagens de log (de uma classe) para o mesmo logger. Mesmo nas raras ocasiões em que uma classe pode querer enviar algumas mensagens para outro criador de logs, seria muito mais claro criar outra variável do criador de logs (por exemplo widgetDetailLogger
), em vez de alterar o valor de uma variável estática em tempo real.
Quando você deseja alterar o valor do campo?
Se você nunca vai mudar o valor, tornar o campo final torna óbvio que você nunca mudará o valor.
Normalmente, você inicializa o criador de logs para fazer logon usando o nome da classe - o que significa que, se eles não fossem estáticos, você terminaria com cada instância da classe (instância de alta memória), mas todos esses criadores de log compartilham a mesma configuração e se comportam exatamente da mesma maneira. Essa é a razão por trás da parte static
. Também porque cada um Logger
é inicializado com o nome da classe, para evitar conflitos com subclasses, você o declara private
para que não possa ser herdado. Definal
vem do ponto que você normalmente não mudar o Logger
durante a execução - assim Uma vez inicializado você nunca "re-configurado"-lo - caso em que faz sentido para torná-lo final para garantir que ninguém pode alterá-lo (por erro ou não). Claro que se você vai usar umLogger
de uma maneira diferente, talvez você NÃO precise usá-lo static final
- mas atrevo-me a supor que 80% dos aplicativos usariam o log como explicado acima.
Para responder a essa pergunta, você deveria ter se perguntado para que servem "estático" e "final".
Para um Logger, (presumo que você fale sobre a classe Log4J Logger), você quer uma categoria por classe. O que deve levar ao fato de que você o atribui apenas uma vez e não há necessidade de mais de uma instância por classe. E, presumivelmente, não há razão para expor o objeto Logger de uma classe para outra, por que não torná-lo privado e seguir alguns princípios OO.
Além disso, você deve observar que o compilador pode tirar proveito disso. Portanto, seu código funciona um pouco melhor :)
Porque esse geralmente é o tipo de funcionalidade que pode ser compartilhada em todas as instâncias de seus objetos. Não faz muito sentido (90% do tempo) ter um criador de logs diferente para duas instâncias da mesma classe.
No entanto, você também pode ver, às vezes, classes de criadores de logs declaradas como singletons ou mesmo simplesmente oferecendo funções estáticas para registrar suas coisas.
Esse código é vulnerável, mas, após o Java7, podemos usar em Logger lgr = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
vez do log estático.
This is code is vulnerable
Você poderia esclarecer que responde um pouco?
Idealmente, o Logger deve ser o seguinte ao Java 7, para não fornecer Sonar e fornecer um código compatível: private: nunca esteja acessível fora da classe pai. Se outra classe precisar registrar algo, deve instanciar seu próprio criador de logs. static: não depende de uma instância de uma classe (um objeto). Ao registrar algo, é claro que as informações contextuais podem ser fornecidas nas mensagens, mas o criador de logs deve ser criado no nível da classe para evitar a criação de um criador de logs junto com cada objeto e, portanto, impedindo a pegada de alta memória. final: seja criado uma vez e apenas uma vez por classe.
Além das razões apresentadas nas outras respostas, uma coisa que encontrei foi que, se meu criador de logs não fosse estático nem final:
...
public Logger logger = LoggerFactory.getLogger(DataSummary.class);
public String toJson() {
GsonBuilder gsonBuilder = new GsonBuilder();
return gsonBuilder.create().toJsonTree(this).toString();
}
...
em certos casos (quando eu estava usando a biblioteca Gson), recebia a exceção stackoverflow. Minha situação específica era instanciar a classe que contém o registrador não final não estático. Em seguida, chame o método toJson que invocou o GsonBuilder:
...
DataSummary ds = new DataSummary(data);
System.out.println(ds.toJson());
...
Na verdade, os registradores estáticos podem ser "prejudiciais", pois devem funcionar em um contexto estático. Ao ter um ambiente dinâmico, por exemplo. OSGi, pode ajudar a usar registradores não estáticos. Como algumas implementações de log fazem um cache interno de loggers (AFAIK pelo menos log4j), o impacto no desempenho pode ser insignificante.
Uma desvantagem dos registradores estáticos é, por exemplo. coleta de lixo (quando uma classe é usada apenas uma vez, por exemplo, durante a inicialização, o criador de logs ainda será mantido).
Para mais detalhes, verifique:
Veja também:
De acordo com as informações que li na internet sobre como tornar o criador de logs estático ou não, a melhor prática é usá-lo de acordo com os casos de uso.
Existem dois argumentos principais:
1) Quando você o torna estático, ele não é coletado como lixo (uso e desempenho da memória).
2) Quando você não o torna estático, ele é criado para cada instância da classe (uso de memória)
Portanto, ao criar um criador de logs para um singleton, você não precisa torná-lo estático. Porque haverá apenas uma instância, portanto, um logger.
Por outro lado, se você estiver criando um criador de logs para um modelo ou classe de entidade, deve ficar estático para não criar criadores de logs duplicados.