Last active
December 22, 2023 12:36
-
-
Save jomoespe/ea5c21722b693c09c38bf6286226cd92 to your computer and use it in GitHub Desktop.
Utility class to handle checked exceptions from
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Utility class to handle checked exceptions in lambdas. | |
* <p> | |
* From <a href="http://stackoverflow.com/questions/27644361/how-can-i-throw-checked-exceptions-from-inside-java-8-streams">How can I throw CHECKED exceptions from inside Java 8 streams?</a>. | |
* This class helps to handle checked exceptions with lambdas. Example, with Class.forName method, which throws checked exceptions: | |
* </p> | |
* <pre> | |
* Stream.of("java.lang.Object", "java.lang.Integer", "java.lang.String") | |
* .map(rethrowFunction(Class::forName)) | |
* .collect(Collectors.toList()); | |
* </pre> | |
* | |
* @author http://stackoverflow.com/users/3411681/marcg | |
*/ | |
public final class LambdaExceptionUtil { | |
@FunctionalInterface | |
public interface Consumer_WithExceptions<T, E extends Exception> { | |
void accept(T t) throws E; | |
} | |
@FunctionalInterface | |
public interface BiConsumer_WithExceptions<T, U, E extends Exception> { | |
void accept(T t, U u) throws E; | |
} | |
@FunctionalInterface | |
public interface Function_WithExceptions<T, R, E extends Exception> { | |
R apply(T t) throws E; | |
} | |
@FunctionalInterface | |
public interface Supplier_WithExceptions<T, E extends Exception> { | |
T get() throws E; | |
} | |
@FunctionalInterface | |
public interface Runnable_WithExceptions<E extends Exception> { | |
void run() throws E; | |
} | |
/** .forEach(rethrowConsumer(name -> System.out.println(Class.forName(name)))); or .forEach(rethrowConsumer(ClassNameUtil::println)); */ | |
public static <T, E extends Exception> Consumer<T> rethrowConsumer(Consumer_WithExceptions<T, E> consumer) { | |
return t -> { | |
try { consumer.accept(t); } | |
catch (Exception exception) { throwAsUnchecked(exception); } | |
}; | |
} | |
public static <T, U, E extends Exception> BiConsumer<T, U> rethrowBiConsumer(BiConsumer_WithExceptions<T, U, E> biConsumer) { | |
return (t, u) -> { | |
try { biConsumer.accept(t, u); } | |
catch (Exception exception) { throwAsUnchecked(exception); } | |
}; | |
} | |
/** .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) { | |
return t -> { | |
try { return function.apply(t); } | |
catch (Exception exception) { throwAsUnchecked(exception); return null; } | |
}; | |
} | |
/** rethrowSupplier(() -> new StringJoiner(new String(new byte[]{77, 97, 114, 107}, "UTF-8"))), */ | |
public static <T, E extends Exception> Supplier<T> rethrowSupplier(Supplier_WithExceptions<T, E> function) { | |
return () -> { | |
try { return function.get(); } | |
catch (Exception exception) { throwAsUnchecked(exception); return null; } | |
}; | |
} | |
/** uncheck(() -> Class.forName("xxx")); */ | |
public static void uncheck(Runnable_WithExceptions t) { | |
try { t.run(); } | |
catch (Exception exception) { throwAsUnchecked(exception); } | |
} | |
/** uncheck(() -> Class.forName("xxx")); */ | |
public static <R, E extends Exception> R uncheck(Supplier_WithExceptions<R, E> supplier) { | |
try { return supplier.get(); } | |
catch (Exception exception) { throwAsUnchecked(exception); return null; } | |
} | |
/** uncheck(Class::forName, "xxx"); */ | |
public static <T, R, E extends Exception> R uncheck(Function_WithExceptions<T, R, E> function, T t) { | |
try { return function.apply(t); } | |
catch (Exception exception) { throwAsUnchecked(exception); return null; } | |
} | |
@SuppressWarnings ("unchecked") | |
private static <E extends Throwable> void throwAsUnchecked(Exception exception) throws E { | |
throw (E)exception; | |
} | |
} | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class LambdaExceptionUtilTest { | |
@Test | |
public void test_Consumer_with_checked_exceptions() throws IllegalAccessException { | |
Stream.of("java.lang.Object", "java.lang.Integer", "java.lang.String") | |
.forEach(rethrowConsumer(className -> System.out.println(Class.forName(className)))); | |
Stream.of("java.lang.Object", "java.lang.Integer", "java.lang.String") | |
.forEach(rethrowConsumer(System.out::println)); | |
} | |
@Test | |
public void test_Function_with_checked_exceptions() throws ClassNotFoundException { | |
List<Class> classes1 | |
= Stream.of("Object", "Integer", "String") | |
.map(rethrowFunction(className -> Class.forName("java.lang." + className))) | |
.collect(Collectors.toList()); | |
List<Class> classes2 | |
= Stream.of("java.lang.Object", "java.lang.Integer", "java.lang.String") | |
.map(rethrowFunction(Class::forName)) | |
.collect(Collectors.toList()); | |
} | |
@Test | |
public void test_Supplier_with_checked_exceptions() throws ClassNotFoundException { | |
Collector.of( | |
rethrowSupplier(() -> new StringJoiner(new String(new byte[]{77, 97, 114, 107}, "UTF-8"))), | |
StringJoiner::add, StringJoiner::merge, StringJoiner::toString); | |
} | |
@Test | |
public void test_uncheck_exception_thrown_by_method() { | |
Class clazz1 = uncheck(() -> Class.forName("java.lang.String")); | |
Class clazz2 = uncheck(Class::forName, "java.lang.String"); | |
} | |
@Test (expected = ClassNotFoundException.class) | |
public void test_if_correct_exception_is_still_thrown_by_method() { | |
Class clazz3 = uncheck(Class::forName, "INVALID"); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment