SonarLint私は次の行に問題があることを示しています。組み込みの文字列フォーマットとログパラメータとしての文字列連結
LOGGER.debug("Comparing objects: " + object1 + " and " + object2);
サイドノート:この行を含むメソッドが頻繁に呼び出されることがあります。
この問題の説明は、「前提条件」とロギング引数は評価 (イカ:S2629)を必要としないはず
ある
グアバ com.googleにさらなる評価が必要なメッセージの引数を渡します。 common.base.Preconditionsチェックの結果、パフォーマンスは になります。それは、メソッドが実際に呼び出される前に、それぞれの引数 を解決する必要があるかどうかが理由です。同様に
、連結は、ログ レベルがメッセージを表示するために十分に低いかどうか、メソッドが呼び出されるたびに 実行されますので、ロギング方式に連結された文字列を渡すとも 不要なパフォーマンスヒットが発生することができます。
代わりに、静的またはあらかじめ計算された の値を前提条件のチェックとロギングの呼び出しに渡すようにコードを構造化する必要があります。
具体的には、内蔵の文字列フォーマットではなく 文字列の連結を使用する必要があり、メッセージがメソッド 呼び出しの結果である場合、前提条件はaltoghetherをスキップしなければならない、と 関連例外が条件付きでスローされるべきです代わりに。
違反コード
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
適合
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()); }
私は私がこの権利を理解しているかどうか100%わかりません。では、なぜこれが本当に問題なのですか?特に、文字列連結を使用するときのパフォーマンスヒットに関する部分。私はしばしばその文字列を読むので、連結はそれをフォーマットするより速いです。
EDIT:たぶん誰かが
LOGGER.debug("Comparing objects: " + object1 + " and " + object2);
と
LOGGEr.debug("Comparing objects: {} and {}",object1, object2);
の違いはバックグラウンドで動作している私を説明することができます。私はStringがメソッドに渡される前に作成されると思うからです。右?だから私にとっては違いはありません。しかし、明らかに私は間違っていますSonarLintはそれについて不平を言っているので
Icaroの答えは、文字列連結がはるかに高速であるという事実を述べています。だから私はなぜこれが問題なのだろうと思っています。 StringBuilderについて - > Icaroの答えでAmirRaminarのコメントが表示された場合、コンパイラによって "+"がStringBuilderコールに変換されていることがわかりました。 – Naxos84
次のコメントは私にとってもっと面白いです;) – luso