web-dev-qa-db-ja.com

例外をスローするJava 8 Lambda関数?

Stringパラメータを持ち、intを返すメソッドへの参照を作成する方法を知っています。

Function<String, Integer>

ただし、関数が例外をスローした場合、これは機能しません。次のように定義されているとします。

Integer myMethod(String s) throws IOException

この参照をどのように定義しますか?

401
Triton Man

次のいずれかを実行する必要があります。

  • それがあなたのコードであるならば、チェックされた例外を宣言するあなた自身の機能的なインターフェースを定義します:

    @FunctionalInterface
    public interface CheckedFunction<T, R> {
       R apply(T t) throws IOException;
    }
    

    そしてそれを使う:

    void foo (CheckedFunction f) { ... }
    
  • それ以外の場合は、Integer myMethod(String s)をチェック済み例外を宣言しないメソッドでラップします。

    public Integer myWrappedMethod(String s) {
        try {
            return myMethod(s);
        }
        catch(IOException e) {
            throw new UncheckedIOException(e);
        }
    }
    

    その後:

    Function<String, Integer> f = (String t) -> myWrappedMethod(t);
    

    または

    Function<String, Integer> f =
        (String t) -> {
            try {
               return myMethod(t);
            }
            catch(IOException e) {
                throw new UncheckedIOException(e);
            }
        };
    
350
jason

Java 8の デフォルトのメソッド !を使って、例外を処理する新しいインターフェースでConsumer(そしてFunctionなど)を実際に拡張することができます。

このインターフェースを考えてください(Consumerを拡張します):

@FunctionalInterface
public interface ThrowingConsumer<T> extends Consumer<T> {

    @Override
    default void accept(final T elem) {
        try {
            acceptThrows(elem);
        } catch (final Exception e) {
            // Implement your own exception handling logic here..
            // For example:
            System.out.println("handling an exception...");
            // Or ...
            throw new RuntimeException(e);
        }
    }

    void acceptThrows(T elem) throws Exception;

}

次に、たとえばリストがあるとします。

final List<String> list = Arrays.asList("A", "B", "C");

もし例外を投げるようなコードでそれを(例えばforEachで)消費したいのであれば、伝統的にtry/catchブロックを設定していたでしょう:

final Consumer<String> consumer = aps -> {
    try {
        // maybe some other code here...
        throw new Exception("asdas");
    } catch (final Exception ex) {
        System.out.println("handling an exception...");
    }
};
list.forEach(consumer);

しかし、この新しいインタフェースでは、ラムダ式でインスタンス化することができ、コンパイラは文句を言いません。

final ThrowingConsumer<String> throwingConsumer = aps -> {
    // maybe some other code here...
    throw new Exception("asdas");
};
list.forEach(throwingConsumer);

あるいは、もっと簡潔にするためにキャストするだけでいいのです。

list.forEach((ThrowingConsumer<String>) aps -> {
    // maybe some other code here...
    throw new Exception("asda");
});

更新 Durian の非常にいいユーティリティライブラリの一部である{ Errors があるので、この問題をもっと柔軟に解決することができます。たとえば、上記の私の実装では、エラー処理ポリシー(System.out...またはthrow RuntimeException)を明示的に定義しましたが、Durianのエラーを使用すると、多数のユーティリティメソッドを使用してポリシーをその場で適用できます。 共有する 、@NedTwigg!をありがとう。

使用例

list.forEach(Errors.rethrow().wrap(c -> somethingThatThrows(c)));
178
jlb

DurianのErrorsクラス は上記のさまざまな提案の長所の多くを兼ね備えています。

Durianをプロジェクトに含めるには、次のいずれかを行います。

  • jcenter または maven central からcom.diffplug.durian:durian:3.3.0で入手してください。
  • または単に2つの小さなクラスをコピーしてコードにコピーします。 Throwing.Java および Errors.Java
57
Ned Twigg

これはJava 8に固有のものではありません。あなたは以下と同等のものをコンパイルしようとしています。

interface I {
    void m();
}
class C implements I {
    public void m() throws Exception {} //can't compile
}
27
assylias

免責事項:私はまだJava 8を使っていません。読んでください。

Function<String, Integer>IOExceptionをスローしないので、throws IOExceptionというコードを入れることはできません。 Function<String, Integer>を期待するメソッドを呼び出している場合、そのメソッドに渡すラムダはIOException、periodをスローすることはできません。このようにラムダを書くこともできます(私はこれがラムダ構文だと思いますが、確信はありません)。

(String s) -> {
    try {
        return myMethod(s);
    } catch (IOException ex) {
        throw new RuntimeException(ex);
        // (Or do something else with it...)
    }
}

あるいは、ラムダを渡しているメソッドが自分で書いたものである場合は、新しい関数型インタフェースを定義し、それをFunction<String, Integer>の代わりにパラメータ型として使用できます。

public interface FunctionThatThrowsIOException<I, O> {
    O apply(I input) throws IOException;
}
12
Adam R. Nelson

サードパーティのlib( Vavr )を使用しても構わない場合は、次のように書くことができます。

CheckedFunction1<String, Integer> f = this::myMethod;

エラーを処理する、いわゆるTryモナドもあります。

Try(() -> f.apply("test")) // results in a Success(Integer) or Failure(Throwable)
        .map(i -> ...) // only executed on Success
        ...

もっと読んでください ここ

免責事項:私はVavrの作成者です。

7
Daniel Dietrich

使用不可ラッパーを使用できます

Function<String, Integer> func1 = s -> Unthrow.wrap(() -> myMethod(s));

または

Function<String, Integer> func2 = s1 -> Unthrow.wrap((s2) -> myMethod(s2), s1);
6
SeregaLBN

ただし、以下のようにスローされる独自のFunctionalInterfaceを作成することもできます。

@FunctionalInterface
public interface UseInstance<T, X extends Throwable> {
  void accept(T instance) throws X;
}

次に、以下に示すように、ラムダまたは参照を使用してそれを実装します。

import Java.io.FileWriter;
import Java.io.IOException;

//lambda expressions and the execute around method (EAM) pattern to
//manage resources

public class FileWriterEAM  {
  private final FileWriter writer;

  private FileWriterEAM(final String fileName) throws IOException {
    writer = new FileWriter(fileName);
  }
  private void close() throws IOException {
    System.out.println("close called automatically...");
    writer.close();
  }
  public void writeStuff(final String message) throws IOException {
    writer.write(message);
  }
  //...

  public static void use(final String fileName, final UseInstance<FileWriterEAM, IOException> block) throws IOException {

    final FileWriterEAM writerEAM = new FileWriterEAM(fileName);    
    try {
      block.accept(writerEAM);
    } finally {
      writerEAM.close();
    }
  }

  public static void main(final String[] args) throws IOException {

    FileWriterEAM.use("eam.txt", writerEAM -> writerEAM.writeStuff("sweet"));

    FileWriterEAM.use("eam2.txt", writerEAM -> {
        writerEAM.writeStuff("how");
        writerEAM.writeStuff("sweet");      
      });

    FileWriterEAM.use("eam3.txt", FileWriterEAM::writeIt);     

  }


 void writeIt() throws IOException{
     this.writeStuff("How ");
     this.writeStuff("sweet ");
     this.writeStuff("it is");

 }

}
5
JohnnyO

あなたはできる。

@marcgのUtilExceptionを拡張し、必要に応じて一般的な<E extends Exception>を追加します。このようにして、コンパイラは再びthrow句を追加するように強制します。

public final class LambdaExceptionUtil {

    @FunctionalInterface
    public interface Function_WithExceptions<T, R, E extends Exception> {
        R apply(T t) throws E;
    }

    /**
     * .map(rethrowFunction(name -> Class.forName(name))) or .map(rethrowFunction(Class::forName))
     */
    public static <T, R, E extends Exception> Function<T, R> rethrowFunction(Function_WithExceptions<T, R, E> function) throws E  {
        return t -> {
            try {
                return function.apply(t);
            } catch (Exception exception) {
                throwActualException(exception);
                return null;
            }
        };
    }

    @SuppressWarnings("unchecked")
    private static <E extends Exception> void throwActualException(Exception exception) throws E {
        throw (E) exception;
    }

}

public class LambdaExceptionUtilTest {

    @Test
    public void testFunction() throws MyTestException {
        List<Integer> sizes = Stream.of("ciao", "hello").<Integer>map(rethrowFunction(s -> transform(s))).collect(toList());
        assertEquals(2, sizes.size());
        assertEquals(4, sizes.get(0).intValue());
        assertEquals(5, sizes.get(1).intValue());
    }

    private Integer transform(String value) throws MyTestException {
        if(value==null) {
            throw new MyTestException();
        }
        return value.length();
    }

    private static class MyTestException extends Exception { }
}
5
PaoloC

すでにここに掲載されている偉大な回答がたくさんあります。違う視点で問題を解決しようとしているだけです。それはちょうど私の2セントです、私がどこか間違っているならば私を訂正してください。

FunctionalInterfaceのThrows節はお勧めできません

以下の理由から、これはIOExceptionをスローするように強制するためのおそらく良い考えではないと思います

  • これは私にはStream/Lambdaに対するアンチパターンのように見えます。全体的なアイデアは、呼び出し元がどのコードを提供し、どのように例外を処理するかを決定するということです。多くのシナリオで、IOExceptionはクライアントには適用されない可能性があります。たとえば、クライアントが実際のI/Oを実行する代わりにキャッシュ/メモリから価値を得ている場合です。

  • また、ストリームでの例外処理は非常に厄介になります。例えば、これは私があなたのAPIを使用した場合のコードです。

               acceptMyMethod(s -> {
                    try {
                        Integer i = doSomeOperation(s);
                        return i;
                    } catch (IOException e) {
                        // try catch block because of throws clause
                        // in functional method, even though doSomeOperation
                        // might not be throwing any exception at all.
                        e.printStackTrace();
                    }
                    return null;
                });
    

    醜いですね。さらに、最初のポイントで述べたように、doSomeOperationメソッドは(クライアント/呼び出し元の実装に応じて)IOExceptionをスローすることもしないこともありますが、FunctionalInterfaceメソッドのthrows節のために、常に次のように記述します。キャッチしよう。

このAPIがIOExceptionをスローすることが本当にわかっている場合はどうすればよいですか

  • それでは、おそらくFunctionalInterfaceと典型的なInterfaceを混同しているでしょう。このAPIがIOExceptionをスローすることがわかっている場合は、おそらくデフォルトの/抽象的な振る舞いも知っているでしょう。私はあなたが以下のようにインタフェースを定義し、あなたのライブラリを(デフォルト/抽象実装で)デプロイするべきだと思います

    public interface MyAmazingAPI {
        Integer myMethod(String s) throws IOException;
    }
    

    しかし、クライアントにはtry-catch問題がまだあります。私があなたのAPIをストリームで使っているのであれば、それでもやはりひどいtry-catchブロックでIOExceptionを処理する必要があります。

  • 次のようにデフォルトのストリームフレンドリなAPIを提供します。

    public interface MyAmazingAPI {
        Integer myMethod(String s) throws IOException;
    
        default Optional<Integer> myMethod(String s, Consumer<? super Exception> exceptionConsumer) {
            try {
                return Optional.ofNullable(this.myMethod(s));
            } catch (Exception e) {
                if (exceptionConsumer != null) {
                    exceptionConsumer.accept(e);
                } else {
                    e.printStackTrace();
                }
            }
    
            return Optional.empty();
        }
    }
    

    デフォルトのメソッドはコンシューマオブジェクトを引数として取り、例外を処理します。今、クライアントの観点から、コードはこのようになります

    strStream.map(str -> amazingAPIs.myMethod(str, Exception::printStackTrace))
                    .filter(Optional::isPresent)
                    .map(Optional::get).collect(toList());
    

    いいですね。もちろん、Exception :: printStackTraceの代わりにロガーや他の処理ロジックを使用することもできます。

  • https://docs.Oracle.com/javase/8/docs/api/Java/util/concurrent/CompletableFuture.html#exceptionally-Java.util.function.Function- のようなメソッドを公開することもできます。 。以前のメソッド呼び出しからの例外を含む別のメソッドを公開できるという意味です。欠点は、現在APIをステートフルにしていることです。これは、スレッドセーフを処理する必要があることを意味し、これは最終的にパフォーマンスの低下につながります。ただし、検討するだけの選択肢です。

4
TriCore

この問題も私を悩ませています。これが、私が このプロジェクト を作成した理由です。

それであなたはできる:

final ThrowingFunction<String, Integer> f = yourMethodReferenceHere;

JDKによって定義された39のインタフェースがあり、それらはそのような同等のThrowingを持ちます。これらはすべてストリームで使用される@FunctionalInterfaceです(基本のStreamだけでなくIntStreamLongStreamおよびDoubleStreamも)。

そしてそれらのそれぞれがそれらの投げられない対応物を拡張するので、あなたは同様にラムダでそれらを直接使うことができます:

myStringStream.map(f) // <-- works

デフォルトの振る舞いは、投げているラムダがチェック例外を投げるとき、原因としてチェック例外を使ってThrownByLambdaExceptionが投げられることです。あなたはそれを捉えて原因を究明することができます。

他の機能も利用できます。

4
fge

卑劣な投げ方イディオム Lambda式のCheckedExceptionのバイパスを有効にします。 CheckedExceptionRuntimeExceptionにラップすることは、厳密なエラー処理には向いていません。

Javaコレクションで使用される Consumer 関数として使用できます。

これが jib's answer の単純で改良されたバージョンです。

import static Throwing.rethrow;

@Test
public void testRethrow() {
    thrown.expect(IOException.class);
    thrown.expectMessage("i=3");

    Arrays.asList(1, 2, 3).forEach(rethrow(e -> {
        int i = e.intValue();
        if (i == 3) {
            throw new IOException("i=" + i);
        }
    }));
}

これは rethrow でラムダをラップするだけです。それはCheckedExceptionがあなたのラムダに投げられたどんなExceptionも再投げるようにします。

public final class Throwing {
    private Throwing() {}

    @Nonnull
    public static <T> Consumer<T> rethrow(@Nonnull final ThrowingConsumer<T> consumer) {
        return consumer;
    }

    /**
     * The compiler sees the signature with the throws T inferred to a RuntimeException type, so it
     * allows the unchecked exception to propagate.
     * 
     * http://www.baeldung.com/Java-sneaky-throws
     */
    @SuppressWarnings("unchecked")
    @Nonnull
    public static <E extends Throwable> void sneakyThrow(@Nonnull Throwable ex) throws E {
        throw (E) ex;
    }

}

完全なコードと単体テストを探す ここ

4
myui

私はラムダの中のClass.forNameとClass.newInstanceでこの問題を抱えていたので、私はちょうどしました:

public Object uncheckedNewInstanceForName (String name) {

    try {
        return Class.forName(name).newInstance();
    }
    catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
        throw new RuntimeException(e);
    }
}

Class.forName( "myClass")。newInstance()を呼び出す代わりに、ラムダ内でuncheckedNewInstanceForName( "myClass")と呼びました。

4
Sergio

Functionラッパーを使用するもう1つの解決策は、すべてがうまくいった場合は成功という、結果のラッパーのいずれかのインスタンスを返すことです。

物事を明確にするためのいくつかのコード:

public interface ThrowableFunction<A, B> {
    B apply(A a) throws Exception;
}

public abstract class Try<A> {

    public static boolean isSuccess(Try tryy) {
        return tryy instanceof Success;
    }

    public static <A, B> Function<A, Try<B>> tryOf(ThrowableFunction<A, B> function) {
        return a -> {
            try {
                B result = function.apply(a);
                return new Success<B>(result);
            } catch (Exception e) {
                return new Failure<>(e);
            }
        };
    }

    public abstract boolean isSuccess();

    public boolean isError() {
        return !isSuccess();
    }

    public abstract A getResult();

    public abstract Exception getError();
}

public class Success<A> extends Try<A> {

    private final A result;

    public Success(A result) {
        this.result = result;
    }

    @Override
    public boolean isSuccess() {
        return true;
    }

    @Override
    public A getResult() {
        return result;
    }

    @Override
    public Exception getError() {
        return new UnsupportedOperationException();
    }

    @Override
    public boolean equals(Object that) {
        if(!(that instanceof Success)) {
            return false;
        }
        return Objects.equal(result, ((Success) that).getResult());
    }
}

public class Failure<A> extends Try<A> {

    private final Exception exception;

    public Failure(Exception exception) {
        this.exception = exception;
    }

    @Override
    public boolean isSuccess() {
        return false;
    }

    @Override
    public A getResult() {
        throw new UnsupportedOperationException();
    }

    @Override
    public Exception getError() {
        return exception;
    }
}

簡単なユースケース:

List<Try<Integer>> result = Lists.newArrayList(1, 2, 3).stream().
    map(Try.<Integer, Integer>tryOf(i -> someMethodThrowingAnException(i))).
    collect(Collectors.toList());
3
yohan

これには _ et _ を使用できます。 ETは例外の変換/翻訳のための小さなJava 8ライブラリです。

ETの場合、このようになります。

// Do this once
ExceptionTranslator et = ET.newConfiguration().done();

...

// if your method returns something
Function<String, Integer> f = (t) -> et.withReturningTranslation(() -> myMethod(t));

// if your method returns nothing
Consumer<String> c = (t) -> et.withTranslation(() -> myMethod(t));

ExceptionTranslatorインスタンスはスレッドセーフであり、複数のコンポーネントで共有できます。必要に応じて、より具体的な例外変換規則(FooCheckedException -> BarRuntimeExceptionなど)を設定できます。他に利用可能な規則がない場合、チェック済みの例外は自動的にRuntimeExceptionに変換されます。

(免責事項:私はETの著者です)

3
micha

私がしていることは、例外の場合にユーザーが実際に欲しい値を与えることをユーザーに許可することです。だから私はこのように見えるものがあります

public static <T, R> Function<? super T, ? extends R> defaultIfThrows(FunctionThatThrows<? super T, ? extends R> delegate, R defaultValue) {
    return x -> {
        try {
            return delegate.apply(x);
        } catch (Throwable throwable) {
            return defaultValue;
        }
    };
}

@FunctionalInterface
public interface FunctionThatThrows<T, R> {
    R apply(T t) throws Throwable;
}

そしてこれは次のように呼ぶことができます。

defaultIfThrows(child -> child.getID(), null)
2
mmounirou

デフォルトでは、Java 8 Function は例外をスローすることを許可していません。複数の回答で示唆されているように、それを達成するには多くの方法があります。

@FunctionalInterface
public interface FunctionWithException<T, R, E extends Exception> {
    R apply(T t) throws E;
}

次のように定義します。

private FunctionWithException<String, Integer, IOException> myMethod = (str) -> {
    if ("abc".equals(str)) {
        throw new IOException();
    }
  return 1;
};

そしてthrowsまたはtry/catchを呼び出し側のメソッドに同じ例外を追加します。

2
Arpit

チェック済みの例外を伝播するカスタムの戻り型を作成します。これは、機能インターフェースのメソッドに「例外をスローする」というわずかな変更を加えて、既存の機能インターフェースを反映した新しいインターフェースを作成する代わりの方法です。

定義

CheckedValueSupplier

public static interface CheckedValueSupplier<V> {
    public V get () throws Exception;
}

CheckedValue

public class CheckedValue<V> {
    private final V v;
    private final Optional<Exception> opt;

    public Value (V v) {
        this.v = v;
    }

    public Value (Exception e) {
        this.opt = Optional.of(e);
    }

    public V get () throws Exception {
        if (opt.isPresent()) {
            throw opt.get();
        }
        return v;
    }

    public Optional<Exception> getException () {
        return opt;
    }

    public static <T> CheckedValue<T> returns (T t) {
        return new CheckedValue<T>(t);
    }

    public static <T> CheckedValue<T> rethrows (Exception e) {
        return new CheckedValue<T>(e);
    }

    public static <V> CheckedValue<V> from (CheckedValueSupplier<V> sup) {
        try {
            return CheckedValue.returns(sup.get());
        } catch (Exception e) {
            return Result.rethrows(e);
        }
    }

    public static <V> CheckedValue<V> escalates (CheckedValueSupplier<V> sup) {
        try {
            return CheckedValue.returns(sup.get());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

}

使用法

//  Don't use this pattern with FileReader, it's meant to be an
//  example.  FileReader is a Closeable resource and as such should
//  be managed in a try-with-resources block or in another safe
//  manner that will make sure it is closed properly.

//  This will not compile as the FileReader constructor throws
//  an IOException.
    Function<String, FileReader> sToFr =
        (fn) -> new FileReader(Paths.get(fn).toFile());

// Alternative, this will compile.
    Function<String, CheckedValue<FileReader>> sToFr = (fn) -> {
        return CheckedValue.from (
            () -> new FileReader(Paths.get("/home/" + f).toFile()));
    };

// Single record usage
    // The call to get() will propagate the checked exception if it exists.
    FileReader readMe = pToFr.apply("/home/README").get();


// List of records usage
    List<String> paths = ...; //a list of paths to files
    Collection<CheckedValue<FileReader>> frs =
        paths.stream().map(pToFr).collect(Collectors.toList());

// Find out if creation of a file reader failed.
    boolean anyErrors = frs.stream()
        .filter(f -> f.getException().isPresent())
        .findAny().isPresent();

どうしたの?

JDKのすべての機能インタフェースに「例外をスローする」を追加すると、DRYの原則に反する最悪の方法で違反します。これを回避するために、チェック済み例外をスローする単一の機能インターフェースが作成されます(CheckedValueSupplier)。これは、チェック済み例外を許可する唯一の機能的インタフェースです。他のすべての機能インターフェースは、CheckedValueSupplierを利用して、チェック済み例外をスローするコードをラップします。

CheckedValueクラスは、チェック済み例外をスローするロジックを実行した結果を保持します。これにより、コードがCheckedValueのインスタンスに含まれる値にアクセスしようとする時点まで、チェック済み例外が伝搬されるのを防ぎます。

このアプローチの問題点.

  • 我々は現在、最初に投げられた特定のタイプを効果的に隠して「例外」を投げています。
  • CheckedValue#get()が呼び出されるまで、例外が発生したことを知りません。

消費者ら

いくつかの機能的なインターフェース(例えばConsumer)は戻り値を提供しないので異なる方法で扱われなければなりません。

消費者の代わりに機能

1つのアプローチは、ストリームを処理するときに適用されるコンシューマの代わりに関数を使用することです。

    List<String> lst = Lists.newArrayList();
// won't compile
lst.stream().forEach(e -> throwyMethod(e));
// compiles
lst.stream()
    .map(e -> CheckedValueSupplier.from(
        () -> {throwyMethod(e); return e;}))
    .filter(v -> v.getException().isPresent()); //this example may not actually run due to lazy stream behavior

エスカレート

あるいは、常にRuntimeExceptionにエスカレートすることができます。 Consumer内からのチェック済み例外のエスカレーションをカバーする他の答えがあります。

消費しないでください。

機能的なインターフェースをまとめて避けて、洗練されたforループを使用するだけです。

2
justin.hughey

cyclops-react という、私が貢献しているライブラリでサードパーティのライブラリを使っても構わない場合は、 FluentFunctions APIを使って書くことができます。

 Function<String, Integer> standardFn = FluentFunctions.ofChecked(this::myMethod);

ofCheckedはjOOλCheckedFunctionを取り、標準化された(チェックされていない)JDK Java.util.function.Functionにソフト化された参照を返します。

あるいは、FluentFunctions apiを使ってキャプチャした関数を使い続けることができます。

例えば、あなたのメソッドを実行するために、5回までそれを再試行し、あなたが書くことができるその状態を記録すること

  FluentFunctions.ofChecked(this::myMethod)
                 .log(s->log.debug(s),e->log.error(e,e.getMessage())
                 .try(5,1000)
                 .apply("my param");
1
John McClean

Jool Libraryを使用するか、JOOQからjOOλ libraryと言います。未チェックの例外処理インタフェースを提供するだけでなく、Seqクラスに多くの便利なメソッドを提供します。

また、最大16個のパラメーターを持つ機能インターフェースも含まれています。また、さまざまなシナリオで使用されるTupleクラスも提供されています。

Jool Git Link

特にorg.jooq.lambda.fi.util.functionパッケージのライブラリ検索で。それはチェックされた接頭辞付きのJava-8からのすべてのインタフェースを含みます。以下を参考にしてください: -

enter image description here

0
Vinay Prajapati

私は一般的なことをします:

public interface Lambda {

    @FunctionalInterface
    public interface CheckedFunction<T> {

        T get() throws Exception;
    }

    public static <T> T handle(CheckedFunction<T> supplier) {
        try {
            return supplier.get();
        } catch (Exception exception) {
            throw new RuntimeException(exception);

        }
    }
}

使用法:

 Lambda.handle(() -> method());
0
ahll

提供された解決策のいくつかは、スローされる例外のタイプを渡すためにEの一般的な引数を使用します。

さらに一歩進んで、例外の種類を渡すのではなく、次のように例外の種類のConsumerを渡します。

Consumer<E extends Exception>

アプリケーションの一般的な例外処理のニーズをカバーする、Consumer<Exception>の再利用可能なバリエーションをいくつか作成することができます。

0