PMD Javaルール Error Prone

PMDのJavaルールについてまとめます。バージョン6.35.0時のルールとなっています。 非推奨となっているルールには「△」を先頭に付与しています。

バージョン6.35.0から6.47.0までのルールの差分については別の記事でまとめています。 olafnosuke.hatenablog.com

Error Proneカテゴリには、紛らわしい、もしくはランタイムエラーが発生しやすい構造を検出するためのルールを含んでいる。

AssignmentInOperand

オペランド中の代入ロジックを検出

// NG例
public void doSomething() {
    if ((x = getX()) == 10) { // 複雑になり読みにくくなる
      ...
    }
}

// OK例
public void doSomething() {
    int x = getX();
    // 外で代入した値を使用する
    if (x == 10) {
        System.out.println(x);
    }
}

プロパティ

名前 デフォルト値 説明 複数指定
allowIf false ifの条件式内での代入を許可する -
allowFor false forの条件式内での代入を許可する -
allowWhile false whileの条件式内での代入を許可する -
allowIncrementDecrement false if、for、whileの条件式内でインクリメント演算子やデクリメント演算子の使用を許可する -

ルール設定例

<!-- プロパティ設定なし -->
<rule ref="category/java/errorprone.xml/AssignmentInOperand" />

<!-- プロパティ設定あり -->
<rule ref="category/java/errorprone.xml/AssignmentInOperand">
    <properties>
        <property name="allowIf" value="false" />
        <property name="allowFor" value="false" />
        <property name="allowWhile" value="false" />
        <property name="allowIncrementDecrement" value="false" />
    </properties>
</rule>

AssignmentToNonFinalStatic

コンストラクタでstaticフィールドへ代入されていないか

// NG例
static int x;
public Sample(int y) {
    x = y; // 安全じゃない
}

ルール設定例

<rule ref="category/java/errorprone.xml/AssignmentToNonFinalStatic" />

△AvoidAccessibilityAlteration

getDeclaredConstructors()、getDeclaredConstructor(Class[])、setAccessible() などのメソッドをPrivilegedAction以外の場所で呼んでいないか PrivilegedActionはローカルPCから環境変数などの情報を取得するための特権を使用する際に使う。
Webアプリ開発時には不要。

ルール設定例

<rule ref="category/java/errorprone.xml/AvoidAccessibilityAlteration" />

AvoidAssertAsIdentifier

assertという識別子を使用している箇所を検出

// NG例
public void doSomething() {
    // JDK4以降assertは予約語
    // コンパイルエラーになる
   String assert = "not good";
}

ルール設定例

<rule ref="category/java/errorprone.xml/AvoidAssertAsIdentifier" />

AvoidBranchingStatementAsLastInLoop

continueとbreakの変な使用方法を検出

// NG例
public void doSomething() {
    for (int i = 0; i < 10; i++) {
    if (i*i <= 25) {
        continue; // バグや混乱を招く可能性がある
    }
    break;
    }
}

// OK例
for (int i = 0; i < 10; i++) {
    if (i*i > 25) {
        break;
    }
}

プロパティ

名前 デフォルト値 説明 複数指定
checkBreakLoopTypes for|do|while breakの使い方をチェックするループ対象 「|」区切り
checkContinueLoopTypes for|do|while continueの使い方をチェックするループ対象 「|」区切り
checkReturnLoopTypes for|do|while returnの使い方をチェックするループ対象 「|」区切り

ルール設定例

<!-- プロパティ設定なし -->
<rule ref="category/java/errorprone.xml/AvoidBranchingStatementAsLastInLoop" />

<!-- プロパティ設定あり -->
<rule ref="category/java/errorprone.xml/AvoidBranchingStatementAsLastInLoop">
    <properties>
        <property name="checkBreakLoopTypes" value="for|do|while" />
        <property name="checkContinueLoopTypes" value="for|do|while" />
        <property name="checkReturnLoopTypes" value="for|do|while" />
    </properties>
</rule>

AvoidCallingFinalize

Object.finalize()メソッドを明示的に呼び出していないか

// NG例
public void doSomething() {
    Bar b = new Bar();
    b.finalize(); 
    // アプリケーションでロジックの一部として呼ぶべきではない
    // java9以降はDeprecatedになっている + protectedなのでそもそも呼べない
}

ルール設定例

<rule ref="category/java/errorprone.xml/AvoidCallingFinalize" />

AvoidCatchingNPE

NullPointerExceptionをcatchしていないか 通常の状況では、コードが NullPointerExceptions をスローすることはなく、元のエラーを隠し、後々問題を引き起こす可能性がある

// NG例
public void doSomething() {
    try {
    } catch (NullPointerException ex) {
    }
}

ルール設定例

<rule ref="category/java/errorprone.xml/AvoidCatchingNPE" />

AvoidCatchingThrowable

Throwableをcatchしていないか Throwableは範囲が広く、OutOfMemoryError などのランタイムの問題も含まれるので良くない

// NG例
public void doSomething() {
    try {
    } catch (Throwable ex) {
    }
}

ルール設定例

<rule ref="category/java/errorprone.xml/AvoidCatchingThrowable" />

AvoidDecimalLiteralsInBigDecimalConstructor

BigDecimal コンストラクタの引数に数値で小数値を与えている箇所を検出

// NG例
public void doSomething() {
    new BigDecimal(1.123); // 精度が失われる可能性がある
}

// OK例
public void doSomething() {
    new BigDecimal("1.123"); 
}

ルール設定例

<rule ref="category/java/errorprone.xml/AvoidDecimalLiteralsInBigDecimalConstructor" />

AvoidDuplicateLiterals

重複する文字列リテラルを含むコードを検出

// NG例
public void doSomething() {
   // 複数回同じ文字列を使用。
   System.out.println("aaa");
   System.out.println("aaa");
   System.out.println("aaa");
   System.out.println("aaa");
}

// OK例
public void doSomething() {
   String s = "aaa";
   System.out.println(s);
   System.out.println(s);
   System.out.println(s);
   System.out.println(s);
}

プロパティ

名前 デフォルト値 説明 複数指定
separator , リスト区切り文字を無視 -
maxDuplicateLiterals 4 最大重複リテラル -
minimumLength 3 チェックする文字列の最小文字数 -
skipAnnotations false アノテーション内のリテラルをスキップする -
exceptionList 無視するリテラルのリスト 「,」区切り

ルール設定例

<!-- プロパティ設定なし -->
<rule ref="category/java/errorprone.xml/AvoidDuplicateLiterals" />

<!-- プロパティ設定あり -->
<rule ref="category/java/errorprone.xml/AvoidDuplicateLiterals">
    <properties>
        <property name="separator" value="," />
        <property name="maxDuplicateLiterals" value="4" />
        <property name="minimumLength" value="3" />
        <property name="skipAnnotations" value="false" />
        <property name="exceptionList" value="" />
    </properties>
</rule>

AvoidEnumAsIdentifier

enum”が使用されているか

// NG例
public void doSomething() {
    // JDK1.5以降enumは予約語
    // コンパイルエラーになる
   String enum = "not good";
}

ルール設定例

<rule ref="category/java/errorprone.xml/AvoidEnumAsIdentifier" />

AvoidFieldNameMatchingMethodName

メソッド名と同じ名前のフィールド名がないか

// NG例
public String doSomething = "not good";
public void doSomething() {
    // 処理
}

ルール設定例

<rule ref="category/java/errorprone.xml/AvoidFieldNameMatchingMethodName" />

AvoidFieldNameMatchingTypeName

宣言している型名と同じ名前のフィールド名がないか

// NG例
public class Sample {
    public String sample;
}

ルール設定例

<rule ref="category/java/errorprone.xml/AvoidFieldNameMatchingTypeName" />

AvoidInstanceofChecksInCatchClause

catch節の中で例外の種類をチェックしない

// NG例
public void doSomething() {
    try {
    } catch (Exception ex) {
        if (ex instanceof IOException) { // 例外の種類で処理を分けたい場合はcatch節を増やす
            // 例外処理
        }
    }
}

ルール設定例

<rule ref="category/java/errorprone.xml/AvoidInstanceofChecksInCatchClause" />

AvoidLiteralsInIfCondition

ifの条件式でハードコードされたリテラルを使用しない

// NG例
public void doSomething() {
    int i = 3;
    if (i == 10) {
        // 処理
    }
}

// OK例
private static final int MAX_COUNT = 10;
public void doSomething() {
    int i = 3;
    if (i == MAX_COUNT) {
        // 処理
    }
}

プロパティ

名前 デフォルト値 説明 複数指定
ignoreMagicNumbers -1,0 無視するマジックナンバーリスト 「,」区切り
ignoreExpressions true trueの場合単純なif条件のリテラルのみが考慮される。falseの場合は式の中のリテラルもチェックする -

ルール設定例

<!-- プロパティ設定なし -->
<rule ref="category/java/errorprone.xml/AvoidLiteralsInIfCondition" />

<!-- プロパティ設定あり -->
<rule ref="category/java/errorprone.xml/AvoidLiteralsInIfCondition">
    <properties>
        <property name="ignoreMagicNumbers" value="-1,0" />
        <property name="ignoreExpressions" value="true" />
    </properties>
</rule>

AvoidLosingExceptionInformation

例外のインスタンスから得た情報を使用しているかどうか

// NG例
public void doSomething() {
    try {
    } catch (Exception ex) {
        ex.getMessage(); // getしているだけで戻り値を使用していない
    }
}

ルール設定例

<rule ref="category/java/errorprone.xml/AvoidLosingExceptionInformation" />

AvoidMultipleUnaryOperators

複数の単項演算子を使用しない

// NG例
int i = - -1;
boolean b = !!true;

// OK例
int i = 1;
boolean b = true;

ルール設定例

<rule ref="category/java/errorprone.xml/AvoidMultipleUnaryOperators" />

AvoidUsingOctalValues

整数をゼロから始めない

// NG例
int i = 012; // 0始まりは8進数として解釈される

// OK例
int i = 12;

プロパティ

名前 デフォルト値 説明 複数指定
strict false 00と07の間の違反を検出するか -

ルール設定例

<!-- プロパティ設定なし -->
<rule ref="category/java/errorprone.xml/AvoidUsingOctalValues" />

<!-- プロパティ設定あり -->
<rule ref="category/java/errorprone.xml/AvoidUsingOctalValues">
    <properties>
        <property name="strict" value="false" />
    </properties>
</rule>

BadComparison

Double.NaN との等価比較をしていないか

// NG例
boolean x = (y == Double.NaN);

ルール設定例

<rule ref="category/java/errorprone.xml/BadComparison" />

BeanMembersShouldSerialize

Beanクラスの中でgetter,setterが定義されているか

// NG例
private String name; //getter, setterが必要。命名規則に従っていない場合も検出される

プロパティ

名前 デフォルト値 説明 複数指定
ignoredAnnotations lombok.Data| lombok.Getter| lombok.Value このルールで無視するアノテーションの完全修飾名 「|」区切り
prefix スキップする変数のプレフィックス -

ルール設定例

<!-- プロパティ設定なし -->
<rule ref="category/java/errorprone.xml/BeanMembersShouldSerialize" />

<!-- プロパティ設定あり -->
<rule ref="category/java/errorprone.xml/BeanMembersShouldSerialize">
    <properties>
        <property name="ignoredAnnotations" value="lombok.Data|lombok.Getter|lombok.Value" />
        <property name="prefix" value="" />
    </properties>
</rule>

BrokenNullCheck

NullPointerExceptionをスローするようなNullチェックが行われていないか

// NG例
public String doSomething() {
    String string = "string";
    if (string != null || !string.equals("")){
        return string;
    }
    if (string == null && string.equals("")){
        return string;
    }
    return string;
}

ルール設定例

<rule ref="category/java/errorprone.xml/BrokenNullCheck" />

CallSuperFirst

android.app.Activity、android.app.Application、android.app.Serviceを継承したクラスは、メソッドの開始時に super を呼び出す必要がある

// NG例
public class DummyActivity extends Activity {
    public void onCreate(Bundle bundle) {
        // missing call to super.onCreate(bundle)
        foo();
    }
}

ルール設定例

<rule ref="category/java/errorprone.xml/CallSuperFirst" />

CallSuperLast

android.app.Activity、android.app.Application、android.app.Serviceを継承したクラスは、メソッドの終了時に super を呼び出す必要がある

// NG例
public class DummyActivity extends Activity {
    public void onCreate(Bundle bundle) {
        foo();
        // missing call to super.onCreate(bundle)
    }
}

ルール設定例

<rule ref="category/java/errorprone.xml/CallSuperLast" />

CheckSkipResult

InputStream.skip() メソッドは、要求されたバイト数よりも少ないバイト数をスキップする場合があるので、きちんとスキップされたかチェックする必要がある

// NG例
public void skip(int n) throws IOException {
    FileInputStream _s = new FileInputStream("file");
    _s.skip(n); // You are not sure that exactly n bytes are skipped
}

// OK例
public void skipExactly(int n) throws IOException {
     FileInputStream _s = new FileInputStream("file");
     while (n != 0) {
        long skipped = _s.skip(n);
        if (skipped == 0){
            throw new EOFException();
        }
        n -= skipped;
     }
}

ルール設定例

<rule ref="category/java/errorprone.xml/CheckSkipResult" />

ClassCastExceptionWithToArray

ClassCastExceptionが発生するようなtoArray()メソッドの使い方をしているところがないか

// NG例
Collection c = new ArrayList();
Integer obj = Integer.valueOf(1);
c.add(obj);
Integer[] a = (Integer [])c.toArray();

// OK例
Integer[] b = (Integer [])c.toArray(new Integer[c.size()]);

ルール設定例

<rule ref="category/java/errorprone.xml/ClassCastExceptionWithToArray" />

CloneMethodMustBePublic

Cloneableを実装するクラスは、パブリックメソッドでObject.clone をオーバーライドする必要がある

// NG例
public class Sample implements Cloneable {
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return null; 
    }
}

// OK例
public class Sample implements Cloneable {
    @Override
    public Object clone() throws CloneNotSupportedException {
        return null; 
    }
}

ルール設定例

<rule ref="category/java/errorprone.xml/CloneMethodMustBePublic" />

CloneMethodMustImplementCloneable

clone()メソッドはCloneableをimplementsしているときのみ実装できる

// NG例
public class Sample  {
    @Override
    public Object clone() throws CloneNotSupportedException {
        return null; 
    }
}

// OK例
public class Sample implements Cloneable {
    @Override
    public Object clone() throws CloneNotSupportedException {
        return null; 
    }
}

ルール設定例

<rule ref="category/java/errorprone.xml/CloneMethodMustImplementCloneable" />

CloneMethodReturnTypeMustMatchClassName

cloneable を実装する場合、メソッド clone() の戻り型はクラス名にする

// NG例
public class Sample implements Cloneable {
    @Override
    public Object clone() throws CloneNotSupportedException {
        return null; 
    }
}

// OK例
public class Sample implements Cloneable {
    @Override
    public Sample clone() throws CloneNotSupportedException {
        return null; 
    }
}

ルール設定例

<rule ref="category/java/errorprone.xml/CloneMethodReturnTypeMustMatchClassName" />

△CloneThrowsCloneNotSupportedException

非推奨のため省略


CloseResource

閉じられていないリソースがないかチェック

// NG例
public void doSomething(String string) throws FileNotFoundException {
    InputStream file = new FileInputStream(new File("/tmp/foo"));
    try {
        byte[] readAllBytes = file.readAllBytes();
    } catch (IOException e) {
        // handle exception
    } 
}

プロパティ

名前 デフォルト値 説明 複数指定
closeTargets このリソースを閉じる可能性があるメソッド 「,」区切り
types java.lang.AutoCloseable, java.sql.Connection, java.sql.Statement, java.sql.ResultSet 影響のある型 「,」区切り
closeAsDefaultTarget true スキップする変数のプレフィックス -
allowedResourceTypes java.io.ByteArrayOutputStream| java.io.ByteArrayInputStream| java.io.StringWriter| java.io.CharArrayWriter| java.util.stream.Stream| java.util.stream.IntStream| java.util.stream.LongStream| java.util.stream.DoubleStream クローズする必要のないクラス名 「|」区切り
closeNotInFinally false 'close' (または他の closeTargets) がfinallyの外で呼び出されたかどうかを検出するか -

ルール設定例

<!-- プロパティ設定なし -->
<rule ref="category/java/errorprone.xml/CloseResource" />

<!-- プロパティ設定あり -->
<rule ref="category/java/errorprone.xml/CloseResource">
    <properties>
        <property name="closeTargets" value="" />
        <property name="types" value="java.lang.AutoCloseable,java.sql.Connection,java.sql.Statement,java.sql.ResultSet" />
        <property name="closeAsDefaultTarget" value="true" />
        <property name="allowedResourceTypes" value="java.io.ByteArrayOutputStream|java.io.ByteArrayInputStream|java.io.StringWriter|java.io.CharArrayWriter|java.util.stream.Stream|java.util.stream.IntStream|java.util.stream.LongStream|java.util.stream.DoubleStream" />
        <property name="closeNotInFinally" value="false" />
    </properties>
</rule>

CompareObjectsWithEquals

オブジェクト参照の比較時にequals()を使用しているか

// NG例
public void doSomething() {
    String s1 = "";
    String s2 = "ss";
    if (s1 == s2) {
        // 処理
    }
}

// OK例
public void doSomething() {
    String s1 = "";
    String s2 = "ss";
    if (s1.equals(s2)) {
        // 処理
    }
}

プロパティ

名前 デフォルト値 説明 複数指定
typesThatCompareByReference java.lang.Enum, java.lang.Class 参照比較が許可される型名のリスト 「,」区切り

ルール設定例

<!-- プロパティ設定なし -->
<rule ref="category/java/errorprone.xml/CompareObjectsWithEquals" />

<!-- プロパティ設定あり -->
<rule ref="category/java/errorprone.xml/CompareObjectsWithEquals">
    <properties>
        <property name="typesThatCompareByReference" value="java.lang.Enum,java.lang.Class" />
    </properties>
</rule>

ConstructorCallsOverridableMethod

コンストラクタの実装にそのクラスのオーバライド可能なメソッドを呼び出す処理がないか

// NG例
public class Parent {
    public Parent() {
        toString();
    }

    public String toString() {
        return "IAmSeniorClass";
    }
}
public class Child extends Parent {
    private String name;

    public Child() {
        super(); //Automatic call leads to NullPointerException
        name = "JuniorClass";
    }

    public String toString() {
        return name.toUpperCase();
    }
}

ルール設定例

<rule ref="category/java/errorprone.xml/ConstructorCallsOverridableMethod" />

△DataflowAnomalyAnalysis

非推奨のため省略


DetachedTestCase

テストケースに見えるメソッドがないか

// NG例
class SampleTest {

    @Test
    void test() {
    }

    void something() {
    }
}

// OK例
class SampleTest {

    @Test
    void test() {
    }

    private void something() { 
    }
}

ルール設定例

<rule ref="category/java/errorprone.xml/DetachedTestCase" />

DoNotCallGarbageCollectionExplicitly

System.gc()、Runtime.getRuntime().gc()、および System.runFinalization() を呼んでいないか

// NG例
public void doSomething()  {
    System.gc();
}

ルール設定例

<rule ref="category/java/errorprone.xml/DoNotCallGarbageCollectionExplicitly" />

DoNotExtendJavaLangThrowable

Throwableを継承したクラスがないか

// NG例
public class SampleException extends Throwable {
}

// OK例
public class SampleException extends Exception  {
}

ルール設定例

<rule ref="category/java/errorprone.xml/DoNotExtendJavaLangThrowable" />

DoNotHardCodeSDCard

Androidでsdcardのパスをハードコーディングしない

// NG例
public class MyActivity extends Activity {
    protected void foo() {
        String storageLocation = "/sdcard/mypackage";
    }
}

ルール設定例

<rule ref="category/java/errorprone.xml/DoNotHardCodeSDCard" />

DoNotTerminateVM

System.exit()を呼んでいないか

// NG例
public void doSomething()  {
    System.exit(0);
}

ルール設定例

<rule ref="category/java/errorprone.xml/DoNotTerminateVM" />

DoNotThrowExceptionInFinally

finallyで例外をスローしていないか

// NG例
public void doSomething()  {
    try {
        // 処理
    } finally {
         throw new Exception();
    }
}

ルール設定例

<rule ref="category/java/errorprone.xml/DoNotThrowExceptionInFinally" />

DontImportSun

sun.*で始まるimport文がないか

// NG例
import sun.misc.foo;
public class Foo {}

ルール設定例

<rule ref="category/java/errorprone.xml/DontImportSun" />

DontUseFloatTypeForLoopIndices

ループのインデックスにfloatを使用していないか

// NG例
public void doSomething()  {
    for (float f = 0; f <= 3; f++) {
        // 処理
    }
}

ルール設定例

<rule ref="category/java/errorprone.xml/DontUseFloatTypeForLoopIndices" />

EmptyCatchBlock

空のcatch節がないか

// NG例
public void doSomething() {
    try {
        FileInputStream fis = new FileInputStream("/tmp/bugger");
    } catch (IOException ioe) {
    }
}

// OK例
public void doSomething() {
    try {
        FileInputStream fis = new FileInputStream("/tmp/bugger");
    } catch (IOException ex) {
        // catch節に処理を追加する
        logger.error("例外です", ex);
    }
}

プロパティ

名前 デフォルト値 説明 複数指定
allowCommentedBlocks false コメントを含む空のブロックは許可する -
allowExceptionNameRegex ^(ignored|expected)$ この正規表現に一致する名前で例外をキャッチする空のブロックは許可する -

ルール設定例

<!-- プロパティ設定なし -->
<rule ref="category/java/errorprone.xml/EmptyCatchBlock" />

<!-- プロパティ設定あり -->
<rule ref="category/java/errorprone.xml/EmptyCatchBlock">
    <properties>
        <property name="allowCommentedBlocks" value="false" />
        <property name="allowExceptionNameRegex" value="^(ignored|expected)$" />
    </properties>
</rule>

EmptyFinalizer

空のファイナライザーがないか

// NG例
public class Sample {
    protected void finalize() {
    }
}

ルール設定例

<rule ref="category/java/errorprone.xml/EmptyFinalizer" />

EmptyFinallyBlock

空のfinallyブロックがないか

// NG例
public void doSomething()  {
    try {
        // 処理
    } finally {
    }
}

ルール設定例

<rule ref="category/java/errorprone.xml/EmptyFinallyBlock" />

EmptyIfStmt

空の if ステートメントがないか

// NG例
public void doSomething(String s)  {
    if(s == null){
    }
}

ルール設定例

<rule ref="category/java/errorprone.xml/EmptyIfStmt" />

EmptyInitializer

空のイニシャライザがないか

// NG例
public class Sample {
    static {}
}

ルール設定例

<rule ref="category/java/errorprone.xml/EmptyInitializer" />

EmptyStatementBlock

空のブロックステートメントがないか

// NG例
public void doSomething()  {
    {}
}

ルール設定例

<rule ref="category/java/errorprone.xml/EmptyStatementBlock" />

EmptyStatementNotInLoop

無駄な空文がないか

// NG例
public void doSomething()  {
    ;
}

ルール設定例

<rule ref="category/java/errorprone.xml/EmptyStatementNotInLoop" />

EmptySwitchStatements

空のswitchがないか

// NG例
public void doSomething()  {
    int x = 2;
    switch (x) {
    }
}

ルール設定例

<rule ref="category/java/errorprone.xml/EmptySwitchStatements" />

EmptySynchronizedBlock

空のsynchronizedブロックがないか

// NG例
public void doSomething()  {
    synchronized (this) {
    }
}

ルール設定例

<rule ref="category/java/errorprone.xml/EmptySynchronizedBlock" />

EmptyTryBlock

空のtryブロックがないか

// NG例
public void doSomething() {
    try {
    } catch (Exception e) {
         e.printStackTrace();
    }
}

ルール設定例

<rule ref="category/java/errorprone.xml/EmptyTryBlock" />

EmptyWhileStmt

空のwhileステートメントがないか

// NG例
public void doSomething() {
    int a = 2;
    int b = 3;
    while (a == b) {
    }
}

ルール設定例

<rule ref="category/java/errorprone.xml/EmptyWhileStmt" />

EqualsNull

equals()でnullと比較されていないか

// NG例
public void doSomething() {
    String x = "foo";
    if (x.equals(null)){
        // 処理
    }
}

ルール設定例

<rule ref="category/java/errorprone.xml/EqualsNull" />

FinalizeDoesNotCallSuperFinalize

finalize()メソッドの最後でsuper.finalize()を呼び出しているか

// NG例
public class Sample {
    protected void finalize() {
        // 処理
    }
}

ルール設定例

<rule ref="category/java/errorprone.xml/FinalizeDoesNotCallSuperFinalize" />

FinalizeOnlyCallsSuperFinalize

super.finalize()だけを呼び出していないか

// NG例
public class Sample {
    protected void finalize() {
        super.finalize(); // java9以降非推奨
    }
}

ルール設定例

<rule ref="category/java/errorprone.xml/FinalizeOnlyCallsSuperFinalize" />

FinalizeOverloaded

finalize()メソッドをオーバーロードしていないか

// NG例
public class Sample {
    protected void finalize(int a) {
    }
}

ルール設定例

<rule ref="category/java/errorprone.xml/FinalizeOverloaded" />

FinalizeShouldBeProtected

finalize()メソッドがprotectedで宣言されているか

// NG例
public class Sample {
    public void finalize() {
    }
}

ルール設定例

<rule ref="category/java/errorprone.xml/FinalizeShouldBeProtected" />

IdempotentOperations

べき等演算をしていないか

// NG例
public void doSomething() {
    int a = 2;
    a = a;
}

ルール設定例

<rule ref="category/java/errorprone.xml/IdempotentOperations" />

△ImportFromSamePackage

非推奨のため省略


InstantiationToGetClass

getClass() を呼び出すためだけにオブジェクトをインスタンス化していないか

// NG例
Class c = new String().getClass();

// OK例
Class c = String.class;

ルール設定例

<rule ref="category/java/errorprone.xml/InstantiationToGetClass" />

InvalidLogMessageFormat

slf4j および log4j2 (6.19.0 以降) ロガーで、引数とプレースホルダーの数が一致しないメッセージがないか

// NG例
logger.error("forget the arg %s");

ルール設定例

<rule ref="category/java/errorprone.xml/InvalidLogMessageFormat" />

JumbledIncrementer

間違ったインクリメント文を検出する

// NG例
for (int i = 0; i < 10; i++) {
  for (int k = 0; k < 20; i++) { // k++の間違い
    ...
  }
}

ルール設定例

<rule ref="category/java/errorprone.xml/JumbledIncrementer" />

JUnitSpelling

Junit3用:setUp()とtearDown()のメソッド名スペルミス検出

ルール設定例

<rule ref="category/java/errorprone.xml/JUnitSpelling" />

JUnitStaticSuite

Junit3用suite()がpublic staticであるか

ルール設定例

<rule ref="category/java/errorprone.xml/JUnitStaticSuite" />

△LoggerIsNotStaticFinal

非推奨のため省略


MethodWithSameNameAsEnclosingClass

コンストラクタ以外でクラス名と同じメソッド名のメソッドはないか

// NG例
public class Sample {
    public void Sample(){
    }
}

ルール設定例

<rule ref="category/java/errorprone.xml/MethodWithSameNameAsEnclosingClass" />

MisplacedNullCheck

見当違いなnullチェックでないか

// NG例
public void doSomething() {
     String a = null;
     String baz = "baz";
     if (a.equals(baz) && a != null) {
     } 
}

ルール設定例

<rule ref="category/java/errorprone.xml/MisplacedNullCheck" />

MissingBreakInSwitch

break文が記述されていないswitch文がないか

// NG例
public void doSomething() {
    int status = 1;
    switch (status) {
    case 1:
        System.out.println("1");
    case 2:
        System.out.println("2");
        break;      
    }
}

ルール設定例

<rule ref="category/java/errorprone.xml/MissingBreakInSwitch" />

MissingSerialVersionUID

SerialVersionUIDが定義されているか

// NG例
public class Book implements Serializable {
    String name;
    
    public String getName(){
        return name;
    }
    
    public void setName(String name){
        this.name = name;
    }
}

ルール設定例

<rule ref="category/java/errorprone.xml/MissingSerialVersionUID" />

MissingStaticMethodInNonInstantiatableClass

staticメソッドおよびpublicコンストラクタが存在しないクラスを検出

// NG例
public class Sample
    private Sample(){
    }
  
    void foo() {
    }
}

プロパティ

名前 デフォルト値 説明 複数指定
annotations org.springframework.beans.factory.annotation.Autowired, javax.inject.Inject コンストラクターにこれらのいずれかのアノテーションが付けられている場合、クラスは無視される 「,」区切り

ルール設定例

<!-- プロパティ設定なし -->
<rule ref="category/java/errorprone.xml/MissingStaticMethodInNonInstantiatableClass" />

<!-- プロパティ設定あり -->
<rule ref="category/java/errorprone.xml/MissingStaticMethodInNonInstantiatableClass">
    <properties>
        <property name="annotations" value="org.springframework.beans.factory.annotation.Autowired,javax.inject.Inject" />
    </properties>
</rule>

MoreThanOneLogger

クラス内に複数のLoggerが宣言されていないか

// NG例
public class Sample
    Logger log = Logger.getLogger(Sample.class);
    Logger log2 = Logger.getLogger(Sample.class);
}

ルール設定例

<rule ref="category/java/errorprone.xml/MoreThanOneLogger" />

NonCaseLabelInSwitchStatement

switch文でcaseラベル以外が記述されていないか

// NG例
public void doSomething() {
    int status = 1;
    switch (status) {
    case 1:
        System.out.println("1");
        break;
    mycase 2:
        System.out.println("2");
        break;      
    }
}

ルール設定例

<rule ref="category/java/errorprone.xml/NonCaseLabelInSwitchStatement" />

NonStaticInitializer

staticでないinitializerがあるか

// NG例
public class Sample
    {
        // 処理
    }
}

ルール設定例

<rule ref="category/java/errorprone.xml/NonStaticInitializer" />

NullAssignment

変数宣言以外で変数にnullが設定されていないか

// NG例
public void doSomething() {
     String a = null;
     a = "aaa";
     
     a = null;
}

ルール設定例

<rule ref="category/java/errorprone.xml/NullAssignment" />

OverrideBothEqualsAndHashcode

equals(Object other) と hashCode() の片方しか定義されていないクラスを検出

// NG例
public class Book {

    public boolean equals(Object o) {
        return true;
    }
}

ルール設定例

<rule ref="category/java/errorprone.xml/OverrideBothEqualsAndHashcode" />

ProperCloneImplementation

super.clone() が呼び出されていない clone() メソッドを検出

// NG例
public class Book {
    public Object clone() {
        return new Book();
    }
}

ルール設定例

<rule ref="category/java/errorprone.xml/ProperCloneImplementation" />

ProperLogger

Loggerがprivate static finalで宣言されているか

// NG例
public class Sample
    Logger log = Logger.getLogger(Sample.class);
}

プロパティ

名前 デフォルト値 説明 複数指定
staticLoggerName LOG staticなロガー変数の名前 -
loggerName log Loggerインスタンス変数の名前 -
loggerClass Log ロガーのクラス名 -

ルール設定例

<!-- プロパティ設定なし -->
<rule ref="category/java/errorprone.xml/ProperLogger" />

<!-- プロパティ設定あり -->
<rule ref="category/java/errorprone.xml/ProperLogger">
    <properties>
        <property name="staticLoggerName" value="LOG" />
        <property name="loggerName" value="log" />
        <property name="loggerClass" value="Log" />
    </properties>
</rule>

ReturnEmptyArrayRatherThanNull

配列を返すメソッドでnullではなく空の配列を返しているか

// NG例
public int[] doSomething() {
    return null;
    
// OK例
public int[] doSomething() {
    return new int[10];
}

ルール設定例

<rule ref="category/java/errorprone.xml/ReturnEmptyArrayRatherThanNull" />

ReturnFromFinallyBlock

finallyブロックからreturnしていないか

// NG例
public String doSomething()  {
    try {
        throw new Exception("a");
    } finally {
        return "abcde";
    }
}

ルール設定例

<rule ref="category/java/errorprone.xml/ReturnFromFinallyBlock" />

SimpleDateFormatNeedsLocale

SimpleDateFormat生成時にロケールが指定されているか

// NG例
private SimpleDateFormat format = new SimpleDateFormat("pattern");

ルール設定例

<rule ref="category/java/errorprone.xml/SimpleDateFormatNeedsLocale" />

SingleMethodSingleton

オーバーロードされたgetInstanceメソッドがないか

// NG例
public class Book {
    private static Book book = new Book( );
    
    public static Book getInstance( ) {
        return book;
    }

    public static Book getInstance(Object obj){
        Book book = (Book) obj;
        return book;
    }
}

ルール設定例

<rule ref="category/java/errorprone.xml/SingleMethodSingleton" />

SingletonClassReturningNewInstance

シングルトンクラスはインスタンスを1つだけ持つ

// NG例
public class Book {
    private static Book book = null;
    
    public static Book getInstance( ) {
        synchronized(Book.class) {
            return new Book(); 
        }
    }
}

ルール設定例

<rule ref="category/java/errorprone.xml/SingletonClassReturningNewInstance" />

StaticEJBFieldShouldBeFinal

EJB にstaticフィールドがfinalで定義されていない箇所を検出

// NG例
public class SomeEJB extends EJBObject implements EJBLocalHome {
    private static int CountA;
}

// OK
public class SomeEJB extends EJBObject implements EJBLocalHome {
    private static final int CountB;    // preferred, read-only access
}

ルール設定例

<rule ref="category/java/errorprone.xml/StaticEJBFieldShouldBeFinal" />

StringBufferInstantiationWithChar

StringBufferのコンストラクタでcharを指定していないか

// NG例
StringBuffer sb1 = new StringBuffer('c');

// OK例
StringBuffer sb2 = new StringBuffer("c");

ルール設定例

<rule ref="category/java/errorprone.xml/StringBufferInstantiationWithChar" />

SuspiciousEqualsMethodName

equals()メソッドと間違えてそうなメソッドがないか

// NG例
public int equals(Object o) {
}

ルール設定例

<rule ref="category/java/errorprone.xml/SuspiciousEqualsMethodName" />

SuspiciousHashcodeMethodName

hashCode()メソッドと間違えてそうなメソッドがないか

// NG例
public int hashcode() {
}

ルール設定例

<rule ref="category/java/errorprone.xml/SuspiciousHashcodeMethodName" />

SuspiciousOctalEscape

疑わしい8進数の記述がないかチェック

// NG例
String s = null;
s = "\128"; // "\12" + "8" と見なされる

ルール設定例

<rule ref="category/java/errorprone.xml/SuspiciousOctalEscape" />

TestClassWithoutTestCases

テストクラスみたいな名前のクラスがないか

// NG例
public class BookTest {
    public void doSomething() {
    }
}

ルール設定例

<rule ref="category/java/errorprone.xml/TestClassWithoutTestCases" />

UnconditionalIfStatement

常にtrueまたはfalseであるif文がないか

// NG例
if(true) {
    // 処理
}

ルール設定例

<rule ref="category/java/errorprone.xml/UnconditionalIfStatement" />

UnnecessaryBooleanAssertion

不要なassertFalse()、assertTrue()がないか

// NG例
class SampleTest {

    @Test
    void test() {
        assertTrue(true);
    }
}

ルール設定例

<rule ref="category/java/errorprone.xml/UnnecessaryBooleanAssertion" />

UnnecessaryCaseChange

不必要なtoUpperCase()、toLowerCase()がないか

// NG例
boolean answer1 = str.toUpperCase().equals("baz"); 

// OK例
boolean answer2 = str.equalsIgnoreCase("baz");

ルール設定例

<rule ref="category/java/errorprone.xml/UnnecessaryCaseChange" />

UnnecessaryConversionTemporary

プリミティブ型を文字列に変換する場合に無駄な一時変数を使用していないか

// NG例
String s1 = new Integer(x).toString(); 

// OK例
String s2 = Integer.toString(x);

ルール設定例

<rule ref="category/java/errorprone.xml/UnnecessaryConversionTemporary" />

UnusedNullCheckInEquals

nullチェックした後、別のオブジェクトの equals()メソッドに渡すのではなく、そのオブジェクトでequals()を呼び出しているか

// NG例
public void doSomething() {
    String s = "";
    String t = "";

    if (s != null && t.equals(s)) {
    }
}

ルール設定例

<rule ref="category/java/errorprone.xml/UnusedNullCheckInEquals" />

UseCorrectExceptionLogging

完全なスタックトレースが確実に出力されるようにするには、2 つの引数 (String と Throwable) を指定した logging ステートメントを使用しているか

// NG例
public void doSomething() {
    try {
        FileInputStream fis = new FileInputStream("/tmp/bugger");
    } catch (IOException ex) {
        logger.error(ex);
    }
}

ルール設定例

<rule ref="category/java/errorprone.xml/UseCorrectExceptionLogging" />

UseEqualsToCompareStrings

== または != を使用した文字列の比較をしていないか

// NG例
public void doSomething() {
    String s = "";

    if (s != "") {
    }
}

ルール設定例

<rule ref="category/java/errorprone.xml/UseEqualsToCompareStrings" />

UselessOperationOnImmutable

String、BigDecimal、BigIntegerに対する無意味なロジックがないか

// NG例
BigDecimal bd = new BigDecimal(10);
bd.add(new BigDecimal(5));

// OK例
BigDecimal bd = new BigDecimal(10);
bd = bd.add(new BigDecimal(5));

ルール設定例

<rule ref="category/java/errorprone.xml/UselessOperationOnImmutable" />

UseLocaleWithCaseConversions

String.toLowerCase()メソッド/toUpperCase()メソッドでロケールが指定されているか

// NG例
String s = a.toLowerCase();

// OK例
String s = a.toLowerCase(Locale.EN);

ルール設定例

<rule ref="category/java/errorprone.xml/UseLocaleWithCaseConversions" />

UseProperClassLoader

getClassLoader()メソッドが使用されていないか

// NG例
 ClassLoader cl = Book.class.getClassLoader();

// OK例
 ClassLoader cl = Thread.currentThread().getContextClassLoader();

ルール設定例

<rule ref="category/java/errorprone.xml/UseProperClassLoader" />

他のカテゴリのルールもまとめています。

Best Practiceカテゴリのまとめはこちら: olafnosuke.hatenablog.com

Code Styleカテゴリのまとめはこちら: olafnosuke.hatenablog.com

Designカテゴリのまとめはこちら: olafnosuke.hatenablog.com

Documentationカテゴリのまとめはこちら: olafnosuke.hatenablog.com

Multithreadingカテゴリのまとめはこちら: olafnosuke.hatenablog.com

Performanceカテゴリのまとめはこちら: olafnosuke.hatenablog.com

Securityカテゴリのまとめはこちら: olafnosuke.hatenablog.com