Javaコードにおける一般的な悪習慣と改善策
Java開発でよく見られる「アンチパターン」をコードスキャンツール(https://github.com/pmd/pmd)から引用し、改善点を共有します。
1 - リソース管理
CloseResource: FileInputStreamなどのリソースは使用後に必ず閉じてください。
FileInputStreamやHttpClientのようなオブジェクトは使用後に適切にクローズする必要があります。
JDK 1.8以降では、try-with-resource構文を使用してリソースをクローズすることが推奨されます。なぜなら、複数のリソースや例外処理において、try-finally構文は最初の例外を失う可能性がありますが、try-with-resourceは最初の例外を保持し、後続の例外はSuppressed exceptionsとして扱われます。これらはgetSuppressed()メソッドで取得できます。
try-with-resourceの例:
try (FileReader fileReader = new FileReader(filePath);
BufferedReader bufferedReader = new BufferedReader(fileReader)) {
// 何らかの処理
}
2 - 疎結合
LooseCoupling: ArrayListのような実装型ではなく、インターフェースを使用してください。
具体的な実装型(ArrayListなど)の使用を避け、インターフェース(Listなど)を使用するべきです。
// 非推奨の方法:
public ArrayList<String> getDataList() {
ArrayList<String> list = new ArrayList<String>();
// 何らかの処理
return list;
}
// 推奨される方法:
public List<String> getDataList() {
List<String> list = new ArrayList<String>();
// 何らかの処理
return list;
}
2番目の方法の利点は、このメソッドの呼び出し元がメソッド内部でどのList
3 - NullPointerExceptionの回避
AvoidCatchingNPE - NullPointerExceptionをキャッチするのではなく、その原因を排除してください。
NullPointerExceptionをキャッチするのではなく、コード内でnull参照のチェックを行うべきです。
プログラムが実行時にNullPointerExceptionをスローするということは、null参照のデリファレンスが存在することを示しています。この種の問題はコード内で解決すべきです。
NullPointerExceptionを根本原因を処理せずにキャッチすることは適切ではありません:
- 単純なnull参照チェックの代わりにNullPointerExceptionをキャッチするには、性能面でのコストがより高くなります。
- tryブロック内の複数の式がNullPointerExceptionをスローする可能性がある場合、例外の発生位置を正確に判断できません。
- プログラムがNullPointerExceptionをスローした後、正常な使用状態になることは稀です。
4 - String型の比較にはequals()メソッドを使用
UseEqualsToCompareStrings - '=='や'!='ではなくequals()を使用して文字列を比較してください。
String型を比較する際は、"=="や"!="ではなくequals()メソッドを使用してください。new String("")で構築されたオブジェクトを比較する場合、==はオブジェクトのアドレスを比較するため、この点に注意が必要です。
5 - null判定には"=="を使用
EqualsNull - nullとの比較にはequals()ではなく"=="を使用してください。
インスタンスがnullかどうか判定する際は、`str == null`のように"=="を使用し、`str.equals(null)`のようにしないでください。
6 - スタックトレースの直接出力を避ける
AvoidPrintStackTrace - printStackTrace()の使用を避け、ロガーを使用してください。
printStackTrace()メソッドで直接スタックトレースを出力するのではなく、ログフレームワークを使用してスタックトレース情報を出力してください。
7 - Integer型の初期化
IntegerInstantiation - new Integer()の使用を避け、Integer.valueOf()を使用してください。
new Integer(param)でIntegerオブジェクトを直接作成するのではなく、Integer.valueOf(param)を使用することを推奨します。
String型のパラメータの場合、Integer.parseInt()メソッドを使用して対応する数値型に解析する方が効率的です。
その他の型(Boolean、Long、Doubleなど)でも、Integerと同様の方法で解析してください。
8 - Boolean型の初期化
BooleanInstantiation - new Boolean()の使用を避け、Boolean.TRUE、Boolean.FALSE、またはBoolean.valueOf()を使用してください。
new Boolean(false)のようなBooleanオブジェクトの作成は避け、グローバルなBooleanインスタンスを使用してください。
Boolean型は1/0の2つの状態しかないため、Boolean.TRUEやBoolean.FALSE、またはBoolean.valueOf()を使用することを推奨します。
参考資料
https://github.com/pmd/pmd