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