Perché dichiariamo Logger statico finale?


131

In Java, perché è consigliabile dichiarare un logger static final?

private static final Logger S_LOGGER

Risposte:


209
  • private- in modo che nessun'altra classe possa dirottare il tuo logger
  • static - quindi esiste una sola istanza del logger per classe, evitando anche tentativi di serializzare i logger
  • final - nessuna necessità di cambiare il logger per tutta la durata della lezione

Inoltre, preferisco che il nome logsia il più semplice possibile, ma descrittivo.

EDIT: Tuttavia c'è un'interessante eccezione a queste regole:

protected final Logger log = LoggerFactory.getLogger(getClass());

al contrario di:

private static final Logger log = LoggerFactory.getLogger(Foo.class);

Il primo modo consente di utilizzare lo stesso nome del logger (nome della classe effettiva) in tutte le classi nella gerarchia ereditaria. Quindi, se si Barestende Foo, entrambi accederanno al Barlogger. Alcuni lo trovano più intuitivo.


36
se statico e finale, piuttosto piuttosto LOG (maiuscolo)
zacheusz,

39
@zacheusz , lo so, questo è il punto. Alcuni seguono religiosamente la convenzione di denominazione Java (niente di sbagliato in questo), ma preferisco scrivere più facilmente e più piacevole leggere il lognome piuttosto che diffondere il codice LOG. Solo una questione di sviluppo. accordo di squadra.
Tomasz Nurkiewicz,

27
Si noti che non è sempre consigliabile dichiarare i logger come statici e finali, vedere slf4j.org/faq.html#declared_static e wiki.apache.org/commons/Logging/FrequentlyAskedQuestions section Devo dichiarare i riferimenti dei log statici o no?
Matthew Farwell,

6
@zacheusz Il nome del campo in maiuscolo viene utilizzato per le costanti. Logger non è costante. http://stackoverflow.com/questions/1417190/should-a-static-final-logger-be-declared-in-upper-case
michal.kreuzman

2
@zacheusz attributi finali non tutti statici dovrebbero essere MAIUSCOLO: stackoverflow.com/questions/1417190/...
bsmk

15

Controlla questo post sul blog: Sbarazzarsi di logger statici Java . Ecco come si usa slf4j con jcabi-log :

import com.jcabi.log.Logger;
class Foo {
  void save(File f) {
    Logger.info(this, "file %s saved successfully", f);
  }
}

E non usare più quel rumore statico.


Un'alternativa interessante e decisamente più pulita. Mi chiedo come questo ridimensiona rispetto ai logger di classe individuali.
Ross,

12
Scrivi Logger più lungo .. (questo, ...) ogni volta. Nah.
Mikhail Boyarsky,

Il primo commento nel relativo post sul blog indica il lato malvagio dei metodi statici :) Quindi usare il Logger finale privato è la migliore pratica immagino.
Bahadir Tasdemir,

5

staticsignifica che crei solo un Logger per classe, non un Logger per istanza della tua classe. In genere, questo è ciò che si desidera, poiché i logger tendono a variare esclusivamente in base alla classe.

finalsignifica che non modificherai il valore della loggervariabile. Il che è vero, dal momento che quasi sempre getti tutti i messaggi di registro (da una classe) allo stesso logger. Anche nelle rare occasioni in cui una classe potrebbe voler inviare alcuni messaggi a un logger diverso, sarebbe molto più chiaro creare un'altra variabile logger (ad es. widgetDetailLogger) Piuttosto che mutare il valore di una variabile statica al volo.


4

Quando vorresti cambiare il valore del campo?

Se non modificherai mai il valore, rendendo definitivo il campo diventa ovvio che non modificherai mai il valore.


1
In molti casi è ovvio senza aggiungere la parola final, che in questo caso diventa una specie di spazzatura.
Dima,

2
@Dima: Beh, io sono ancora grato che il compilatore sarà ancora genera un errore se non sbaglio cerco di cambiare il valore in questi casi ...
Jon Skeet

3

Normalmente si inizializza il logger per accedere usando il nome della classe - il che significa che se non fossero statici, si finirebbe con ogni istanza della classe che ne ha un'istanza (footprint di memoria elevata), ma tutti questi logger dovrebbero condividere la stessa configurazione e comportarsi esattamente allo stesso modo. Questo è il motivo dietro il staticbit. Inoltre, poiché ognuno Loggerè inizializzato con il nome della classe, per evitare conflitti con le sottoclassi, lo si dichiara in privatemodo che non possa essere ereditato. Il fatto finalderiva dal fatto che normalmente non si cambia Loggerdurante l'esecuzione - quindi una volta inizializzato non lo si "riconfigura" mai - nel qual caso ha senso renderlo definitivo per assicurarsi che nessuno possa cambiarlo ( errore o altro). Ovviamente se hai intenzione di usare aLoggerin un altro modo potresti non dover usare static final- ma mi permetto di indovinare l'80% delle app userebbe la registrazione come spiegato sopra.


3

Per rispondere a questa domanda, avresti dovuto chiederti a cosa servono "statico" e "finale".

Per un Logger, (suppongo che tu parli della classe Log4J Logger) vuoi una categoria per classe. Il che dovrebbe portare al fatto che lo si assegna una sola volta e non è necessario più di un'istanza per classe. E presumibilmente non c'è motivo di esporre l'oggetto Logger di una classe a un'altra, quindi perché non renderlo privato e seguire alcuni Principi OO.

Inoltre, dovresti notare che il compilatore è in grado di trarne vantaggio. Quindi il tuo codice funziona un po 'meglio :)


2

Perché questo è di solito il tipo di funzionalità che può essere condivisa in tutte le istanze dei tuoi oggetti. Non ha molto senso (90% delle volte) avere un logger diverso per due istanze della stessa classe.

Tuttavia, a volte puoi anche vedere classi di logger dichiarate come singleton o anche semplicemente offrire funzioni statiche per registrare le tue cose.


2

Questo codice è vulnerabile , ma, dopo Java7, possiamo usare al Logger lgr = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); posto del registratore statico.


This is code is vulnerablePotresti chiarire che hai risposto un po '?
Dmitry Zagorulkin,

1

Nella maggior parte dei casi, non modificherai il riferimento e il finalmodificatore lo segnerà. Non hai bisogno di istanze separate per ogni istanza di classe - quindi static. E prima di tutto questo è per le prestazioni : può essere ottimizzato (finale) e consente di risparmiare memoria (statica).


1

Idealmente Logger dovrebbe essere il seguente fino a Java 7, per non dare Sonar e dare un codice conforme: privato: non essere mai accessibile al di fuori della sua classe genitore. Se un'altra classe deve registrare qualcosa, dovrebbe creare un'istanza del proprio logger. statico: non dipende da un'istanza di una classe (un oggetto). Quando si registra qualcosa, è possibile fornire ovviamente informazioni contestuali nei messaggi, ma il logger deve essere creato a livello di classe per impedire la creazione di un logger insieme a ciascun oggetto e quindi prevenire il footprint di memoria elevata. finale: essere creato una volta e una sola volta per classe.


0

Oltre ai motivi indicati nelle altre risposte, una cosa in cui mi sono imbattuto è che se il mio logger non fosse né statico né definitivo:

...
public Logger logger = LoggerFactory.getLogger(DataSummary.class);

public String toJson() {
  GsonBuilder gsonBuilder = new GsonBuilder();   
  return gsonBuilder.create().toJsonTree(this).toString();
}
...

in alcuni casi (quando stavo usando la libreria Gson) avrei ricevuto un'eccezione stackoverflow. La mia situazione specifica era quella di creare un'istanza della classe contenente il logger non finale non statico. Quindi chiama il metodo toJson che ha invocato GsonBuilder:

...
DataSummary ds = new DataSummary(data);    
System.out.println(ds.toJson());
...

0

In realtà i logger statici possono essere "dannosi" in quanto dovrebbero funzionare in un contesto statico. Quando si ha un ambiente dinamico ad es. OSGi potrebbe essere d'aiuto usare logger non statici. Poiché alcune implementazioni del logging eseguono una memorizzazione nella cache interna dei logger (almeno AFAIK log4j), l'impatto sulle prestazioni potrebbe essere trascurabile.

Uno svantaggio dei registratori statici è ad es. garbage collection (quando una classe viene utilizzata una sola volta, ad es. durante l'inizializzazione, il logger verrà comunque tenuto in giro).

Per maggiori dettagli controlla:

Guarda anche:


0

Secondo le informazioni che ho letto da Internet sul rendere statico o meno il logger, la migliore pratica è usarlo in base ai casi d'uso.

Esistono due argomenti principali:

1) Quando lo rendi statico, non viene raccolto in modo inutile (utilizzo e prestazioni della memoria).

2) Quando non lo rendi statico, viene creato per ogni istanza di classe (utilizzo della memoria)

Pertanto, quando si crea un logger per un singleton, non è necessario renderlo statico. Perché ci sarà solo un'istanza, quindi un logger.

D'altra parte, se si sta creando un logger per un modello o una classe di entità, è necessario rendere statico non creare logger duplicati.


-1

Hai ancora bisogno del logger statico per le classi statiche interne

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.