private void func1() throws java.io.IOException {
java.util.List.of(1, 2, 3)
// 例外が実際に発生した場合の想定
.forEach(e -> {
throw new java.io.IOException();
});
java.util.Optional.ofNullable("val")
// 例外が実際に発生した場合の想定
.map(val -> {
throw new java.io.IOException();
});
}
import java.util.function.Consumer;
import java.util.function.Function;
public class SneakyThrowTest {
@org.junit.jupiter.api.Test
public void test() throws java.io.IOException {
try {
func1();
} catch (java.io.IOException e) {
System.out.println("func1 is thow IOException");
}
try {
func2();
} catch (java.io.IOException e) {
System.out.println("func2 is thow IOException");
}
}
/**
* 検査対象例外付きの関数型(ラムダ式)実装例
* @throws java.io.IOException 検査例外化する場合はThrowに追加
*/
private void func1() throws java.io.IOException {
// 正常系
java.util.List.of(1, 2, 3).stream()
// 例外ラップ関数使用時のFunction実装
.map(SneakyThrowUtil.rethrowFunc(val -> {
return "val" + val;
}))
// 例外ラップ関数使用時のConsumer実装
.forEach(SneakyThrowUtil.rethrowCons(System.out::println));
// 異常系
java.util.List.of(1, 2, 3)
// 例外が実際に発生した場合の想定
.forEach(SneakyThrowUtil.rethrowCons(e -> {
throw new java.io.IOException();
}));
}
/**
* 検査対象例外付きの関数型(ラムダ式)実装例
* @throws java.io.IOException 検査例外化する場合はThrowに追加
*/
private void func2() throws java.io.IOException {
// 正常系
java.util.Optional.ofNullable("val")
// 例外ラップ関数使用時のFunction実装
.map(SneakyThrowUtil.rethrowFunc(val -> {
return val + 1;
}))
// 例外ラップ関数使用時のConsumer実装
.ifPresent(SneakyThrowUtil.rethrowCons(System.out::println));
// 異常系
java.util.Optional.ofNullable("val")
// 例外が実際に発生した場合の想定
.map(SneakyThrowUtil.rethrowFunc(val -> {
throw new java.io.IOException();
}));
}
}
/**
* 関数型処理の非検査例外用Utilty
*/
final class SneakyThrowUtil {
/**
* Constructor
*/
private SneakyThrowUtil() {
}
/**
* sneakyThrowを行う拡張interface
*/
public interface ThrowingConsumer<T> extends Consumer<T> {
@Override
default void accept(final T e) {
try {
accept0(e);
} catch (Throwable ex) {
SneakyThrowUtil.sneakyThrow(ex);
}
}
// 例外をThows可能なaccept0実装
void accept0(T e) throws Throwable;
}
/**
* sneakyThrowを行う拡張interface
*/
public interface ThrowingFunction<T, R> extends Function<T, R> {
@Override
default R apply(T e) {
try {
return apply0(e);
} catch (Throwable ex) {
SneakyThrowUtil.sneakyThrow(ex);
}
// 必ず処理又はThrowされるため到達不能
return null;
}
// 例外をThows可能なapply実装
R apply0(T t) throws Throwable;
}
/**
* 関数型メソッドを非検査例外化する関数
*/
public static <T> Consumer<T> rethrowCons(final ThrowingConsumer<T> consumer) {
return consumer;
}
/**
* 関数型メソッドを非検査例外化する関数
*/
public static <T, R> Function<T, R> rethrowFunc(final ThrowingFunction<T, R> func) {
return func;
}
/**
* 非検査例外としてcompileを通すsneaky-throws処理
* @see {@linkplain <a href="https://www.baeldung.com/java-sneaky-throws">www.baeldung.com</a>}
*/
@SuppressWarnings("unchecked")
private static <E extends Throwable> void sneakyThrow(Throwable ex) throws E {
throw (E) ex;
}
}