minimize

String Exception

文字列に関するルールセットです。

AvoidDuplicateLiterals

重複した文字列定義を検出します。

threshold

検出される重複文字列個数の最小値を指定します。
デフォルトは 4 です。

StringInstantiation

Stringインスタンスを生成している箇所を検出します。

new String("abc"); // これは単に "abc" で良い

StringToString

String.toString() を呼び出している箇所を検出します。

String s = "abc";
v = s.toString(); // toStringを呼ばずとも既にStringです

InefficientStringBuffering

効率の悪いStringBufferの使い方をしている箇所を検出します。

StringBuffer sb = new StringBuffer();
sb.append("a = " + getA()); // +演算子は使わずに以下のようにします
ab.append("a = ").append(getA());

UnnecessaryCaseChange

不必要な大小文字変換をしている箇所を検出します。

boolean b1 = str.toLowerCase().equals("baz"); // これは次のようにする
boolean b2 = str.equalsIgnoreCase("baz");

UseStringBufferLength

StringBufferインスタンスの文字列長を求めるのに、
toString() を使用している箇所を検出します。

StringBuffer sb;
int len1 = sb.toString().length(); // これは次のようにする
int len2 = sb.length();

StringBuffer.toString() の呼び出しは、コストとメモリを消費するので
なるべく避けた方が良いのです。

AppendCharacterWithChar

StringBuffer に1文字を追加するのに char を使用していない箇所を検出します。

sb.append("a"); // これは次のようにする
sb.append('a');

ConsecutiveLiteralAppends

定数を何回も追加している箇所を検出します。

sb.append("Hello").append(" ").append("World"); // これは次のようにする
sb.append("Hello World");//good
threshold

検出される連続追加回数の最小値を指定します。
デフォルトは 1 です。

UseIndexOfChar

indexOf の引数に1文字の文字列を使用している箇所を検出します。

if (s.indexOf("d") >= 0) {
  // これは次のようにする
}
if (s.indexOf('d') >= 0) {
  // こちらの方がパフォーマンスが良い
}

InefficientEmptyStringCheck

空文字を String.trim().length() でチェックしている箇所を検出します。
この検出方法は効率的ではありません。
面倒ですが、文字列を1文字ずつチェックした方がパフォーマンスが上がります。

if (str.trim().length() == 0) {
  // このチェック方法は効率的ではない
}

for (int i = 0; i < str.length(); i++) {
  if (!Character.isWhitespace(str.charAt(i))) {
    // いや、でも正直面倒くさいですよ…
  }
}

InsufficientStringBufferDeclaration

StringBufferインスタンスの生成方法が適切でない箇所を検出します。

StringBuffer はデフォルトで16文字の容量を確保します。
その後、appendが呼ばれる度にappend後の文字列サイズが
容量を超えないことを確認し、超えるようならば容量を倍のサイズで
確保し直します。

StringBuffer bad = new StringBuffer();
bad.append("This is a long string, will exceed the default 16 characters");

この再確保処理は非常にパフォーマンスとメモリを消費する処理になるので
出来る限りStringBufferのインスタンス生成時に
適切な容量のサイズを指定した方が良いのです。

StringBuffer good = new StringBuffer(41);
good.append("This is a long string, which is pre-sized");

UselessStringValueOf

不必要な String.valueOf() の使用を検出します。

int i;
s = "a" + String.valueOf(i); // これは不要
s = "a" + i;  // こちらが良い

一見、どちらも差が無いように見えますが後者の方がパフォーマンスに優れているのです。
+演算子の使用は、内部的に StringBuilder(Buffer) を使っています。
つまり、前者は

StringBuilder buff = new StringBuilder("a");
buff.append(String.valueOf(i));
s = buff.toString();

後者は

StringBuilder buff = new StringBuilder("a");
buff.append(i);
s = buff.toString();

のように展開されます。

前者は数値を文字列化する為にStringインスタンスを作成してそれをappendしているのに対し
後者は直接数値をappendしています。
これにより、不要なStringインスタンスの生成が抑えられます。
まぁ、本当にシビアな状況でしか問題になることは無いとは思いますが
こういう事に気を付けてコーディングする意識は大切です。

StringBufferInstantiationWithChar

StringBufferのコンストラクタにchar値を渡している箇所を検索します。

StringBuffer sb1 = new StringBuffer('c'); // 'c' は文字ではなく数値の99と見なされてしまう

UseEqualsToCompareStrings

文字列を equals で比較している箇所を検出します。

AvoidStringBufferField

StringBuffer 型のフィールドを検出します。
このクラスは非常に大きなメモリ量を確保する可能性がある為、
これをフィールドに持っているとインスタンスが残っている間
そのメモリが開放されないことになり、メモリリークの危険があります。

通常 StringBuffer をフィールドで持つ必要はありません。
持つ必要があるのなら、クラス設計を見直した方がいいでしょう。

[コメント(0)]