では、次は実務レベルで使えるように改良した、
「for-each+例外処理+ログ」テンプレートの汎用(ジェネリクス対応)版を紹介します。
これは「どんな型のデータでも安全にfor-each処理できる汎用テンプレート」として、
実際の業務システムや共通ユーティリティクラスに組み込みやすい構造です。
【実務テンプレート:汎用 for-each 処理+例外+ログ+再利用設計】
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
// =============================================
// ✅ 汎用処理クラス(再利用可能なテンプレート)
// =============================================
public class SafeForEachProcessor<T> {
private static final Logger logger = Logger.getLogger(SafeForEachProcessor.class.getName());
/**
* for-each 処理を安全に実行する共通メソッド
*
* @param items 処理対象のリスト
* @param handler 各要素の処理を定義するラムダ
*/
public void process(List<T> items, SafeHandler<T> handler) {
if (items == null || items.isEmpty()) {
logger.warning("処理対象リストが空またはnullです。処理をスキップします。");
return;
}
for (T item : items) {
try {
handler.handle(item);
} catch (BusinessException e) {
logger.warning("業務エラー(スキップ): " + e.getMessage());
} catch (Exception e) {
logger.log(Level.SEVERE, "予期せぬエラー発生: " + item, e);
}
}
}
}
// =============================================
// ✅ 各要素処理の関数インターフェース(ラムダで渡す)
// =============================================
@FunctionalInterface
interface SafeHandler<T> {
void handle(T item) throws Exception;
}
// =============================================
// ✅ 業務例外(想定内のエラー用)
// =============================================
class BusinessException extends Exception {
public BusinessException(String message) {
super(message);
}
}
// =============================================
// ✅ 使用例:顧客データを安全に処理するクラス
// =============================================
class Customer {
private final String name;
private final int age;
public Customer(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() { return name; }
public int getAge() { return age; }
@Override
public String toString() {
return name + " (" + age + ")";
}
}
// =============================================
// ✅ 実行クラス
// =============================================
import java.util.Arrays;
public class ExampleMain {
public static void main(String[] args) {
List<Customer> customers = Arrays.asList(
new Customer("Alice", 25),
new Customer("Bob", -1), // 無効データ
new Customer("Charlie", 30)
);
SafeForEachProcessor<Customer> processor = new SafeForEachProcessor<>();
processor.process(customers, customer -> {
if (customer.getAge() < 0) {
throw new BusinessException("年齢が不正です: " + customer);
}
System.out.println("処理中: " + customer);
});
}
}
Javaクラス設計の概要
| クラス名 | 役割 |
|---|---|
SafeForEachProcessor<T> | どんなデータ型でも安全にfor-eachできる汎用テンプレート |
SafeHandler<T> | 各要素の処理内容をラムダ式で渡すためのインターフェース |
BusinessException | 業務的に想定内の例外を区別するクラス |
Customer | 処理対象のドメインモデル(例:顧客データ) |
ExampleMain | 実際の呼び出し例(for-each+例外+ログ) |
実務でのベストプラクティス(設計上の工夫)
| 項目 | ベストプラクティス | 解説 |
|---|---|---|
| 共通for-each処理を1か所に集約 | SafeForEachProcessor | 重複する例外処理・ログ処理を共通化し、コードの品質を均一化 |
| ラムダで処理内容を注入 | SafeHandler<T> | 各業務の「中身」を柔軟に定義できる(Strategyパターン風) |
| カスタム例外で制御 | BusinessException | 想定内エラーとシステム障害を明確に区別できる |
| for-each内でtry-catchを行う | 継続可能な処理に必須 | 1件失敗しても全体処理を中断せず続けられる |
| nullチェック/空チェック | 処理前にガード条件 | NPE防止+安全設計 |
| ロガーのレベル設計 | INFO / WARNING / SEVERE | 重要度に応じた出力レベル管理 |
実務応用例(こう発展できる)
SafeForEachProcessorに「リトライ機能」や「結果集計(成功・失敗件数)」を追加。- Spring Boot環境では
@Serviceクラス内で使い、Slf4jログ出力に統一。 SafeHandlerをラムダ式だけでなく「専用クラス」で実装して、テスト容易化。

