基本的なルールセットです。
※PMD 3.9に対応しています。
EmptyCatchBlock
空のcatchブロックがないかチェックします。
コメントが記述されているcatchブロックを許可する場合は
<property name=”allowCommentedBlocks” value=”true” />
を指定します。
public void doSomething()
{
try
{
FileInputStream fis = new FileInputStream("/tmp/bugger");
}
catch (IOException ioe)
{
// catchブロックが空なのでNG
}
}
EmptyIfStmt
空のifステートメントがないかチェックします。
public class Foo
{
void bar(int x)
{
if (x == 0)
{
// ifステートメントが空なのでNG
}
}
}
EmptyWhileStmt
空のwhileステートメントないかチェックします。
public class Foo
{
void bar(int a, int b)
{
while (a == b)
{
// whileステートメントが空なのでNG
}
}
}
EmptyTryBlock
空のtryブロックないかチェックします。
public class Foo
{
public void bar()
{
try
{
// tryブロックが空なのでNG
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
EmptyFinallyBlock
空のfinallyブロックないかチェックします。
public class Foo
{
public void bar()
{
try
{
int x = 2;
}
finally
{
// finallyブロックが空なのでNG
}
}
}
EmptySwitchStatements
空のswitchステートメントないかチェックします。
public class Foo
{
public void bar()
{
int x = 2;
switch (x)
{
// switchステートメントが空なのでNG
}
}
}
JumbledIncrementer
forステートメントのインデックス変数を上書きしていないかチェックします。
public class JumbledIncrementerRule1
{
public void foo()
{
for (int i = 0; i < 10; i++)
{
for (int k = 0; k < 20; i++)
{
// iインデックスを上書きしているのでNG
System.out.println("Hello");
}
}
}
}
ForLoopShouldBeWhileLoop
whileステートメントの方が効率の良いforステートメントがないかチェックします。
public class Foo
{
void bar()
{
//vwhile (true) の方が効率が良いのでNG
for (;true;) true;
}
}
UnnecessaryConversionTemporary
プリミティブ型を文字列に変換する場合に無駄なテンポラリ変数を使用していないかチェックします。
public String convert(int x)
{
// newは不要なのでNG
String foo = new Integer(x).toString();
// こちらの方が良い
return Integer.toString(x);
}
OverrideBothEqualsAndHashcode
equals()メソッドをオーバーライドする場合、hashCode()メソッドもオーバーライドしているかチェックします。
// equals()メソッドしかオーバーライドしていないのでNG
public class Bar
{
public boolean equals(Object o)
{
// do some comparison
}
}
// hashCode()メソッドしかオーバーライドしていないのでNG
public class Baz
{
public int hashCode()
{
// return some hash value
}
}
// equals()メソッドとhashCode()メソッドをオーバーライドしているのでOK
public class Foo
{
public boolean equals(Object other)
{
// do some comparison
}
public int hashCode()
{
// return some hash value
}
}
DoubleCheckedLocking
二重チェックロック・イディオムを使用していないかチェックします。
public class Foo
{
Object baz;
Object bar()
{
if (baz == null)
{
// baz may be non-null yet not fully created
synchronized(this)
{
if (baz == null)
{
baz = new Object();
}
}
}
return baz;
}
}
ReturnFromFinallyBlock
finallyブロックにreturn文がないかチェックします。
public class Bar
{
public String foo()
{
try
{
throw new Exception("My Exception");
}
catch (Exception e)
{
throw e;
}
finally
{
// finallyブロックにreturn文があるのでNG
return "A. O. K.";
}
}
}
EmptySynchronizedBlock
空のsynchronizedブロックがないかチェックします。
public class Foo
{
public void bar()
{
synchronized (this)
{
// synchronizedブロックが空なのでNG
}
}
}
UnnecessaryReturn
無駄なreturnがないかチェックします。
public class Foo
{
public void bar()
{
int x = 42;
// 無駄なreturnなのでNG
return;
}
}
EmptyStaticInitializer
空のstatic初期化子がないかチェックします。
public class Foo
{
static
{
// static初期化子が空なのでNG
}
}
UnconditionalIfStatement
常にtrueまたはfalseであるifステートメントの条件式がないかチェックします。
public class Foo
{
public void close()
{
// 常にtrueなのでNG
if (true)
{
// ...
}
}
}
EmptyStatementNotInLoop
無駄な空文がないかないかチェックします。
public class MyClass
{
public void doit()
{
// 無駄な空文なのでNG
;
// 2つめのセミコロンは無駄な空文なのでNG
System.out.println("look at the extra semicolon");;
}
}
BooleanInstantiation
Booleanオブジェクトのインスタンスを生成していないかチェックします。
public class Foo
{
// Boolean bar = Boolean.TRUE; とすべきなのでNG
Boolean bar = new Boolean("true");
// Boolean buz = Boolean.FALSE; とすべきなのでNG
Boolean buz = Boolean.valueOf(false);
}
UnnecessaryFinalModifier
final宣言されているクラスの中でメソッドがfinal宣言されていないかチェックします。
public final class Foo
{
private final void foo()
{
// final宣言されているクラスの中でメソッドがfinal宣言されているのでNG
}
}
CollapsibleIfStatements
条件式を&&で結合できる二重のifステートメントがないかチェックします。
public class Foo
{
void bar()
{
if (x)
{
if (y)
{
// if (x && y) と書けるのでNG
// do stuff
}
}
}
}
UselessOverridingMethod
オーラライドしているメソッドが、単にスーパークラスで宣言されているメソッドと同じでないかチェックします。
public void foo(String bar)
{
// 単にオーバーライドしているだけなのでNG
super.foo(bar);
}
ClassCastExceptionWithToArray
ClassCastExceptionが発生するようなtoArray()メソッドの使い方をしているところがないかチェックします。
import java.util.ArrayList;
import java.util.Collection;
public class Test
{
public static void main(String[] args)
{
Collection c = new ArrayList();
Integer obj = new Integer(1);
c.add(obj);
// toArray()はObject[]を返すので、ClassCastExceptionが発生
Integer[] a = (Integer [])c.toArray();
// こっちが正解
Integer[] b = (Integer [])c.toArray(new Integer[c.size()]);
}
}
AvoidDecimalLiteralsInBigDecimalConstructor
BigDecimalのコンストラクタの引数に小数値を設定していないかチェックします。
import java.math.BigDecimal;
public class Test
{
public static void main(String[] args)
{
// 精度落ちが発生する場合があるのでNG
BigDecimal bd = new BigDecimal(1.123);
// こっちは問題ない
BigDecimal bd=new BigDecimal("1.123");
BigDecimal bd=new BigDecimal(12);
}
}
UselessOperationOnImmutable
BigDecimal、BigIntegerに対する無意味なロジックがないかチェックします。
import java.math.*;
class Test
{
void method1()
{
BigDecimal bd = new BigDecimal(10);
// bdの内容は変化しない無意味なロジックなのでNG
bd.add(new BigDecimal(5));
}
void method2()
{
BigDecimal bd = new BigDecimal(10);
// こっちは問題ない
bd = bd.add(new BigDecimal(5));
}
}
MisplacedNullCheck
間違った箇所でNullチェックをしていないかチェックします。
public class Foo
{
void bar()
{
if (a.equals(baz) && a != null)
{
}
}
}
UnusedNullCheckInEquals
Nullチェックとequals()メソッド呼出の不適切な組み合わせがないかチェックします。
public class Test
{
public String method1()
{
return "ok";
}
public String method2()
{
return null;
}
public void method(String a)
{
String b;
if (a != null && method1().equals(a))
{
// aのnullチェックをしているので、a.equals(method1())とするべきである
// method1()がnullを返した場合にNullPointerExceptionが発生してしまう
}
if (method1().equals(a) && a != null)
{
// method1()がnullを返した場合にNullPointerExceptionが発生してしまう
}
if (a != null && method1().equals(b))
{
// method1()がnullを返した場合にNullPointerExceptionが発生してしまう
}
if (a != null && "LITERAL".equals(a))
{
}
if (a != null && !a.equals("go"))
{
a = method2();
if (method1().equals(a))
{
}
}
}
}
AvoidThreadGroup
ThreadGroupが使用されていないかチェックします。
※ThreadGroupはスレッドセーフではないメソッドを持っており、使用は推奨されません。
public class Bar
{
void buz()
{
ThreadGroup tg = new ThreadGroup("My threadgroup");
tg = new ThreadGroup(tg, "my thread group");
tg = Thread.currentThread().getThreadGroup();
tg = System.getSecurityManager().getThreadGroup();
}
}
BrokenNullCheck
NullPointerExceptionをスローするようなNullチェックが行われていないかチェックします。
class Foo
{
String munge(String string)
{
// &&を使うべきなのでNG
if (string != null || !string.equals(""))
return string;
// ||を使うべきなのでNG
if (string==null && string.equals(";"))
return string;
}
}
BigIntegerInstantiation
既に存在しているBigInteger型のインスタンスを生成していないかチェックします。
(BigDecimal.ZERO, BigDecimal.ONE, BigDecimal.TEN)
public class Test
{
public static void main(String[] args)
{
// BigInteger.ONEを使うべきなのでNG
BigInteger bi1 = new BigInteger(1);
// BigInteger.ZEROを使うべきなのでNG
BigInteger bi2 = new BigInteger("0");
// BigInteger.ZEROを使うべきなのでNG
BigInteger bi3 = new BigInteger(0.0);
// BigInteger.ZEROを使うべきなのでNG
BigInteger bi4;
bi4 = new BigInteger(0);
}
}
AvoidUsingOctalValues
整数が0から記述されていないかチェックします。
※先頭を0から記述する8進数表記だと見なされます。
public class Foo
{
// 12ではなく10になる
int i = 012;
// 10ではなく8になる
int j = 010;
// 120ではなく80になる
k = i * j;
}
コメント