Por que declaramos final estático de Loggers?

131

Em Java, por que é uma prática recomendada declarar um criador de logs static final?

private static final Logger S_LOGGER
user489041
fonte

Respostas:

209
  • private- para que nenhuma outra classe possa seqüestrar seu logger
  • static - portanto, existe apenas uma instância de logger por classe, evitando também tentativas de serializar os loggers
  • final - não é necessário alterar o logger durante a vida útil da classe

Além disso, prefiro que o nome logseja 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 Barestendido Foo, ambos serão registrados no Barlogger. Alguns acham mais intuitivo.

Tomasz Nurkiewicz
fonte
35
se static e final, em seguida, em vez LOG (maiúsculas)
zacheusz
39
@ zacheusz , eu sei, esse é o ponto. Alguns seguem a convenção de nomenclatura Java religiosamente (nada de errado nisso), mas eu prefiro escrever mais fácil e mais agradável de ler o lognome do que espalhar o código LOG. Apenas uma questão de dev. acordo de equipe.
Tomasz Nurkiewicz
27
Por favor, note que não é mais sempre recomendável madeireiros declarar estático e final, ver slf4j.org/faq.html#declared_static e wiki.apache.org/commons/Logging/FrequentlyAskedQuestions seção Devo declarar Log referências estática ou não?
Matthew Farwell
6
@zacheusz O nome do campo em maiúsculas é usado para constantes. Logger não é constante. http://stackoverflow.com/questions/1417190/should-a-static-final-logger-be-declared-in-upper-case
michal.kreuzman
2
@zacheusz nem todos os atributos finais estáticos devem ser MAIÚSCULOS: stackoverflow.com/questions/1417190/…
bsmk 30/03/14
15

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.

yegor256
fonte
Uma alternativa interessante e definitivamente mais limpa. Eu me pergunto como isso é escalável comparado aos registradores de classe individuais.
217 Ross
12
Escreva Logger mais longo .. (isso, ...) a cada vez. Nah.
Mikhail Boyarsky
O primeiro comentário na postagem do blog relacionado indica o lado ruim dos métodos estáticos :) Portanto, acho que usar o Logger final privado é a melhor prática.
Bahadir Tasdemir 26/02
5

staticsignifica 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.

finalsignifica que você não vai alterar o valor da loggervariá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.

Andrzej Doyle
fonte
4

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.

Jon Skeet
fonte
1
Em muitos casos, é óbvio sem adicionar a palavra final, que neste caso se torna uma espécie de lixo.
Dima
2
@ Dima: Bem, ainda sou grato que o compilador ainda gera um erro se , acidentalmente, tentar alterar o valor nesses casos ...
Jon Skeet #
3

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 privatepara que não possa ser herdado. Definal vem do ponto que você normalmente não mudar o Loggerdurante 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 umLoggerde 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.

Liv
fonte
3

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 :)

Daniel Leschkowski
fonte
2

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.

Vincent Mimoun-Prat
fonte
2

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.

nkduqi
fonte
This is code is vulnerableVocê poderia esclarecer que responde um pouco?
Dmitry Zagorulkin
1

Na maioria dos casos, você não vai alterar a referência e as finalmarcas de modificação. Você não precisa de instâncias separadas para cada instância de classe - então static. E, antes de tudo, isso é para desempenho - ele pode ser otimizado (final) e economiza memória (estático).

zacheusz
fonte
1

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.

Kratika Chaurasia
fonte
0

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());
...
Paulo
fonte
0

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:

ViToni
fonte
0

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.

Bahadir Tasdemir
fonte
-1

Você ainda precisa de um log estático para classes estáticas internas

Al Emu
fonte