En Java, pourquoi est-il recommandé de déclarer un enregistreur static final
?
private static final Logger S_LOGGER
En Java, pourquoi est-il recommandé de déclarer un enregistreur static final
?
private static final Logger S_LOGGER
Réponses:
private
- pour qu'aucune autre classe ne puisse détourner votre enregistreurstatic
- il n'y a donc qu'une seule instance d'enregistreur par classe, évitant également les tentatives de sérialisation des enregistreursfinal
- pas besoin de changer l'enregistreur pendant la durée de vie de la classeDe plus, je préfère que le nom log
soit aussi simple que possible, mais descriptif.
EDIT: Cependant, il existe une exception intéressante à ces règles:
protected final Logger log = LoggerFactory.getLogger(getClass());
par opposition à:
private static final Logger log = LoggerFactory.getLogger(Foo.class);
La première méthode vous permet d'utiliser le même nom d'enregistreur (nom de la classe réelle) dans toutes les classes de la hiérarchie d'héritage. Donc, si Bar
s'étend Foo
, les deux se connecteront à l' Bar
enregistreur. Certains le trouvent plus intuitif.
log
plutôt que de disperser le code avec LOG
. Juste une question de développement. accord d'équipe.
Consultez ce billet de blog: Débarrassez-vous des enregistreurs statiques Java . Voici comment vous utilisez slf4j avec jcabi-log :
import com.jcabi.log.Logger;
class Foo {
void save(File f) {
Logger.info(this, "file %s saved successfully", f);
}
}
Et n'utilisez plus jamais ce bruit statique.
static
signifie que vous ne créez qu'un seul enregistreur par classe, pas un enregistreur par instance de votre classe. En général, c'est ce que vous voulez - car les enregistreurs ont tendance à varier uniquement en fonction de la classe.
final
signifie que vous n'allez pas changer la valeur de la logger
variable. Ce qui est vrai, puisque vous lancez presque toujours tous les messages de journal (d'une classe) au même enregistreur. Même dans les rares occasions où une classe pourrait vouloir envoyer des messages à un autre enregistreur, il serait beaucoup plus clair de créer une autre variable de journalisation (par exemple widgetDetailLogger
) plutôt que de muter la valeur d'une variable statique à la volée.
Quand voudriez-vous changer la valeur du champ?
Si vous ne modifiez jamais la valeur, le fait de rendre le champ définitif indique clairement que vous ne changerez jamais la valeur.
Normalement, vous initialisez l'enregistreur pour qu'il enregistre en utilisant le nom de la classe - ce qui signifie que s'ils n'étaient pas statiques, vous vous retrouveriez avec chaque instance de la classe en ayant une instance (empreinte mémoire élevée), mais tous ces enregistreurs partagent la même configuration et se comportent exactement de la même manière. C'est la raison derrière le static
bit. De plus, parce que chacun Logger
est initialisé avec le nom de la classe, pour éviter les conflits avec les sous-classes, vous le déclarez private
afin qu'il ne puisse pas être hérité. Le final
vient du point que vous normalement ne modifiez pas le Logger
cours de l'exécution - une fois que vous initialisés jamais « reconfiguré » - dans ce cas , il est logique de le rendre définitif pour assurer que personne ne peut changer (par erreur ou autre). Bien sûr, si vous allez utiliser unLogger
d'une manière différente, vous n'aurez peut-être PAS besoin de l'utiliser static final
- mais je me risquerais à penser que 80% des applications utiliseraient la journalisation comme expliqué ci-dessus.
Pour répondre à cette question, vous auriez dû vous demander à quoi servent les termes «statique» et «final».
Pour un enregistreur, (je suppose que vous parlez de la classe Log4J Logger), vous voulez une catégorie par classe. Ce qui devrait conduire au fait que vous ne l'attribuez qu'une seule fois et qu'il n'y a pas besoin de plus d'une instance par classe. Et il n'y a probablement aucune raison d'exposer l'objet Logger d'une classe à une autre, alors pourquoi ne pas le rendre privé et suivre quelques principes OO.
Notez également que le compilateur est capable d'en tirer profit. Donc, votre code fonctionne un peu mieux :)
Parce que c'est généralement le type de fonctionnalité qui peut être partagée entre toutes les instances de vos objets. Cela n'a pas beaucoup de sens (90% du temps) d'avoir un enregistreur différent pour deux instances de la même classe.
Cependant, vous pouvez également voir parfois des classes de journalisation déclarées comme des singletons ou même simplement proposer des fonctions statiques pour enregistrer vos données.
Ce code est vulnérable , mais, après Java7, nous pouvons utiliser à la Logger lgr = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
place d'un enregistreur statique.
This is code is vulnerable
Pourriez-vous clarifier votre réponse un peu?
Dans la plupart des cas, vous n'allez pas modifier la référence et le final
modificateur la marque. Vous n'avez pas besoin d'instances distinctes pour chaque instance de classe - donc static
. Et tout d'abord, c'est pour la performance - il peut être bien optimisé (final) et économise de la mémoire (statique).
Idéalement, Logger devrait être comme suit jusqu'à Java 7, pour ne pas donner de Sonar et donner un code conforme: private: ne jamais être accessible en dehors de sa classe parente. Si une autre classe a besoin de consigner quelque chose, elle doit instancier son propre enregistreur. statique: ne pas être dépendant d'une instance d'une classe (un objet). Lors de la journalisation de quelque chose, des informations contextuelles peuvent bien sûr être fournies dans les messages, mais l'enregistreur doit être créé au niveau de la classe pour éviter de créer un enregistreur avec chaque objet et ainsi empêcher l'empreinte mémoire élevée. final: être créé une et une seule fois par classe.
En plus des raisons données dans les autres réponses, une chose que j'ai rencontrée était que si mon enregistreur n'était ni statique ni définitif:
...
public Logger logger = LoggerFactory.getLogger(DataSummary.class);
public String toJson() {
GsonBuilder gsonBuilder = new GsonBuilder();
return gsonBuilder.create().toJsonTree(this).toString();
}
...
dans certains cas (lorsque j'utilisais la bibliothèque Gson), j'obtiendrais une exception stackoverflow. Ma situation spécifique était d'instancier la classe contenant le logger non statique non final. Appelez ensuite la méthode toJson qui a appelé GsonBuilder:
...
DataSummary ds = new DataSummary(data);
System.out.println(ds.toJson());
...
En fait, les enregistreurs statiques peuvent être «nuisibles» car ils sont censés fonctionner dans un contexte statique. Lorsque vous avez un environnement dynamique, par exemple. OSGi, il peut être utile d'utiliser des enregistreurs non statiques. Comme certaines implémentations de journalisation font une mise en cache des enregistreurs en interne (AFAIK au moins log4j), l'impact sur les performances peut être négligeable.
Un inconvénient des enregistreurs statiques est par exemple. garbage collection (lorsqu'une classe n'est utilisée qu'une seule fois, par exemple lors de l'initialisation, l'enregistreur sera toujours conservé).
Pour plus de détails, consultez:
Voir également:
Selon les informations que j'ai lues sur Internet pour rendre l'enregistreur statique ou non, la meilleure pratique consiste à l'utiliser en fonction des cas d'utilisation.
Il y a deux arguments principaux:
1) Lorsque vous le rendez statique, il n'est pas ramassé (utilisation de la mémoire et performances).
2) Lorsque vous ne le rendez pas statique, il est créé pour chaque instance de classe (utilisation de la mémoire)
Ainsi, lorsque vous créez un enregistreur pour un singleton, vous n'avez pas besoin de le rendre statique. Parce qu'il n'y aura qu'une seule instance donc un enregistreur.
D'autre part, si vous créez un enregistreur pour un modèle ou une classe d'entité, vous devez le rendre statique pour ne pas créer d'enregistreurs dupliqués.