[解決済み] Java 8: ラムダストリーム、例外を含むメソッドによるフィルタリング
質問
Java 8のLambda式を試していて、問題が発生しました。
通常は問題なく動作するのですが、現在、以下のようなメソッドがあります。
IOException
's.
以下のコードを見ていただければと思います。
class Bank{
....
public Set<String> getActiveAccountNumbers() throws IOException {
Stream<Account> s = accounts.values().stream();
s = s.filter(a -> a.isActive());
Stream<String> ss = s.map(a -> a.getNumber());
return ss.collect(Collectors.toSet());
}
....
}
interface Account{
....
boolean isActive() throws IOException;
String getNumber() throws IOException;
....
}
問題は、isActiveメソッドとgetNumberメソッドで起こりうる例外をキャッチしなければならないので、コンパイルできないことです。しかし、以下のように明示的にtry-catch-blockを使用しても、Exceptionをcatchしていないため、まだコンパイルされない。つまり、JDKにバグがあるのか、私がこれらのExceptionをキャッチする方法を知らないのか、どちらかです。
class Bank{
....
//Doesn't compile either
public Set<String> getActiveAccountNumbers() throws IOException {
try{
Stream<Account> s = accounts.values().stream();
s = s.filter(a -> a.isActive());
Stream<String> ss = s.map(a -> a.getNumber());
return ss.collect(Collectors.toSet());
}catch(IOException ex){
}
}
....
}
どうすれば動くようになるのでしょうか?どなたか、正しい解決策をヒントにしていただけませんか?
解決方法は?
例外をキャッチする必要があります。 前に がラムダをエスケープします。
s = s.filter(a -> {
try {
return a.isActive();
} catch (IOException e) {
throw new UncheckedIOException(e);
}
});
ラムダが評価されるのは、あなたが書いた場所ではなく、JDKのクラス内の全く関係のない場所であるという事実を考えてみてください。そこでチェックされた例外が投げられることになるのだが、その場所では宣言されていない。
チェックされた例外をチェックされていない例外に変換するラムダのラッパーを使うことで、この問題に対処できます。
public static <T> T uncheckCall(Callable<T> callable) {
try {
return callable.call();
} catch (RuntimeException e) {
throw e;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
あなたの例は次のように書かれます。
return s.filter(a -> uncheckCall(a::isActive))
.map(Account::getNumber)
.collect(toSet());
私のプロジェクトでは、この問題をラップせずに、コンパイラによる例外チェックを効果的に無効化する方法を用いて対処しています。言うまでもなく、これは慎重に扱うべきもので、プロジェクトに参加する誰もが、宣言されていないところでチェックされた例外が現れる可能性があることを認識しておく必要があります。これがそのコードです。
public static <T> T uncheckCall(Callable<T> callable) {
try {
return callable.call();
} catch (Exception e) {
return sneakyThrow(e);
}
}
public static void uncheckRun(RunnableExc r) {
try {
r.run();
} catch (Exception e) {
sneakyThrow(e);
}
}
public interface RunnableExc {
void run() throws Exception;
}
@SuppressWarnings("unchecked")
private static <T extends Throwable> void sneakyThrow(Throwable t) throws T {
throw (T) t;
}
を取得することが期待できます。
IOException
を投げつけても
collect
はそれを宣言していない。で
ほとんど、しかしすべてではない
現実のケースでは、とにかく例外を再スローして、一般的な失敗として処理したいと思うでしょう。このような場合、明快さや正しさは何も失われません。ただ、例外にその場で対応したくなるようなケースには注意が必要です。開発者は、コンパイラによって
IOException
をキャッチしようとすると、コンパイラは文句を言うでしょう。なぜなら、そのような例外は投げられないと信じ込ませてしまったからです。
関連
-
JavaMailのメール送信が失敗するケースとその説明の分析
-
SocketTimeoutExceptionの解決方法です。読み込みがタイムアウトした
-
[解決済み] 特定のUnicode文字を含むコメントでのJavaコードの実行が許可されているのはなぜですか?
-
[解決済み] リスト内包とラムダ+フィルタの比較
-
[解決済み] Distinct() with lambda?
-
[解決済み] いつ使うか。Java 8+のインターフェイスのデフォルトメソッドと、抽象的なメソッドの比較
-
[解決済み] javaストリームで整数のリストを合計する方法は?
-
[解決済み] Java 8でラムダをパラメータとして受け取るメソッドを定義するにはどうすればよいですか?
-
[解決済み] Java 8のストリーム内部からCHECKED例外を投げるにはどうすればよいですか?
-
[解決済み】Java 8 Lambda関数が例外を投げる?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
jd-gui Java Exceptionが発生しました。
-
JDKの設定時にjava.dllが見つからない、java SE Runtime Environmentが見つからない問題が発生しました。
-
スレッド "main" での例外 java.lang.ArrayIndexOutOfBoundsException: 1
-
SocketTimeoutExceptionです。読み込みがタイムアウトしました
-
テストが見つかりませんでした
-
Maven Pluginの実行がライフサイクル設定の対象外であるエラーの解決
-
[解決済み] Java 8 Iterable.forEach() vs foreachループ
-
[解決済み] Java 8のストリーム内部からCHECKED例外を投げるにはどうすればよいですか?
-
[解決済み】Java 8 Lambda関数が例外を投げる?
-
[解決済み】Java 8:ストリームで例外をスローするメソッドを操作するにはどうすればよいですか?