Intégré dans la chaîne de formatage vs concaténation de chaîne d'abattage paramètre
Je suis en utilisant SonarLint qui m'indique un problème dans la ligne suivante.
LOGGER.debug("Comparing objects: " + object1 + " and " + object2);
Note: La méthode qui contient cette ligne peut être appelé très souvent.
La description de ce problème est
"Conditions préalables" et la journalisation des arguments qui ne devrait pas nécessiter d'évaluation
(squid:S2629)Passage de message d'arguments qui nécessitent une évaluation plus approfondie dans une Goyave
com.google.commun.de la base.Conditions préalables vérification peut entraîner une performance
peine. Parce que si oui ou non ils sont nécessaires, chaque argument
doivent être résolus avant que la méthode est en fait appelé.De même, en passant chaînes concaténées en une méthode de journalisation peut également
subir une inutile de performances, car la concaténation sera
effectué chaque fois que la méthode est appelée, si oui ou non le journal
le niveau est assez bas pour afficher le message.Au lieu de cela, vous devez structurer votre code pour passer en statique ou en pré-calculé
les valeurs dans des conditions Préalables les conditions de vérification et de journalisation des appels.Plus précisément, intégré dans la chaîne de mise en forme doit être utilisé au lieu de
la concaténation de chaîne, et si le message est le résultat d'une méthode
appel, alors les conditions Préalables devraient être ignorées altoghether, et la
exception devrait être conditionnelle jeté à la place.Non Conforme À L'Exemple De Code
logger.log(Level.DEBUG, "Something went wrong: " + message); //Noncompliant; string concatenation performed even when log level too high to show DEBUG messages LOG.error("Unable to open file " + csvPath, e); //Noncompliant Preconditions.checkState(a > 0, "Arg must be positive, but got " + a); //Noncompliant. String concatenation performed even when a > 0 Preconditions.checkState(condition, formatMessage()); //Noncompliant. formatMessage() invoked regardless of condition Preconditions.checkState(condition, "message: %s", formatMessage()); //Noncompliant
Solution Conforme À La
logger.log(Level.SEVERE, "Something went wrong: %s", message); //String formatting only applied if needed logger.log(Level.SEVERE, () -> "Something went wrong: " + message); //since Java 8, we can use Supplier , which will be evaluated lazily LOG.error("Unable to open file {}", csvPath, e); if (LOG.isDebugEnabled() { LOG.debug("Unable to open file " + csvPath, e); //this is compliant, because it will not evaluate if log level is above debug. } Preconditions.checkState(arg > 0, "Arg must be positive, but got %d", a); //String formatting only applied if needed if (!condition) { throw new IllegalStateException(formatMessage()); //formatMessage() only invoked conditionally } if (!condition) { throw new IllegalStateException("message: " + formatMessage()); }
Je ne suis pas sûr à 100% si je comprends bien ce droit. Alors pourquoi est-ce vraiment un problème. En particulier la partie sur les performances lors de l'utilisation de la concaténation de chaîne. Parce que j'ai souvent lu que la concaténation de chaîne est plus rapide que la mise en forme.
EDIT: Peut-être que quelqu'un peut m'expliquer la différence entre
LOGGER.debug("Comparing objects: " + object1 + " and " + object2);
ET
LOGGEr.debug("Comparing objects: {} and {}",object1, object2);
est en arrière-plan. Parce que je pense que la Chaîne sera créée automatiquement avant qu'il est passé à la méthode. Droit? Donc, pour moi, il n'y a pas de différence. Mais évidemment, je suis mal parce que SonarLint est de se plaindre
OriginalL'auteur Naxos84 | 2017-02-22
Vous devez vous connecter pour publier un commentaire.
Je crois que vous avez votre réponse.
Concaténation est calculé au préalable la condition de vérifier. Donc, si vous appelez votre journalisation 10K fois conditionnellement et chacun d'eux prend la valeur false, vous serez en concaténant 10K fois sans raison.
Également vérifier cette rubrique. Et vérifier Icaro la réponse de commentaires.
Prendre un coup d'oeil à StringBuilder trop.
commentaire suivant est plus intéressant pour moi 😉
OriginalL'auteur luso
Examiner ci-dessous la déclaration logging :
qu'est-ce que ce 'debug' ?
C'est le niveau de journalisation de l'énoncé et non pas au niveau de l'ENREGISTREUR.
Voir, il y a 2 niveaux :
a) de la déclaration logging (qui est de débogage ici) :
b) l'autre au niveau de l'ENREGISTREUR. Alors, quel est le niveau de l'objet LOGGER :
Ceci doit aussi être définis dans le code ou dans du xml , le reste il faut au niveau de son ancêtre .
Maintenant pourquoi je vous raconte tout cela ?
Maintenant la déclaration logging sera imprimé (ou en terme plus technique envoyer à son "appender') si et seulement si :
Valeurs possibles d'un Niveau peut être
(Il peut y avoir de plus en fonction de journalisation)
Maintenant, revenons à la question :
sera toujours conduire à la création de la chaîne, même si nous constatons que le niveau de la règle " expliquée ci-dessus échoue.
Cependant,
aura seulement une chaîne de formation si le niveau de la règle expliqué ci-dessus " satisfait.
Alors, qui est plus intelligent ?
Consulter ce url.
OriginalL'auteur Breaking Benjamin
De concaténation de chaîne moyens
LOGGER.info("Le programme a commencé à" + new Date());
Construit dans le formatage de l'enregistreur de moyens
LOGGER.info("Le programme a débuté à {}", new Date());
très bon article pour comprendre la différence
http://dba-presents.com/index.php/jvm/java/120-use-the-built-in-formatting-to-construct-this-argument
Par ailleurs, le gênants
Date
classe a été remplacé par leInstant
. Voir Oracle Tutoriel.OriginalL'auteur Shubham Pandey