java static方法中的异常_如何从Java 8流中抛出检查过的异常?

这,这个LambdaExceptionUtilHelper类允许您使用Java流中的任何检查异常,如下所示:Stream.of("java.lang.Object", "java.lang.Integer", "java.lang.String")

.map(rethrowFunction(Class::forName))

.collect(Collectors.toList());

注Class::forName抛出ClassNotFoundException,也就是查证..流本身也抛出ClassNotFoundException,而不是一些未经检查的异常。public final class LambdaExceptionUtil {@FunctionalInterfacepublic interface Consumer_WithExceptions {

void accept(T t) throws E;

}@FunctionalInterfacepublic interface BiConsumer_WithExceptions {

void accept(T t, U u) throws E;

}@FunctionalInterfacepublic interface Function_WithExceptions {

R apply(T t) throws E;

}@FunctionalInterfacepublic interface Supplier_WithExceptions {

T get() throws E;

}@FunctionalInterfacepublic interface Runnable_WithExceptions {

void run() throws E;

}/** .forEach(rethrowConsumer(name -> System.out.println(Class.forName(name)))); or .

forEach(rethrowConsumer(ClassNameUtil::println)); */public static  Consumer

rethrowConsumer(Consumer_WithExceptions consumer) throws E {

return t -> {

try { consumer.accept(t); }

catch (Exception exception) { throwAsUnchecked(exception); }

};

}public static  BiConsumer rethrowBiConsumer(BiConsumer_WithExceptions biConsumer) throws E {

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  Function rethrowFunction(Function_WithExceptions function) throws E {

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  Supplier rethrowSupplier(Supplier_WithExceptions function) throws E {

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 uncheck(Supplier_WithExceptions supplier)

{

try { return supplier.get(); }

catch (Exception exception) { throwAsUnchecked(exception); return null; }

}/** uncheck(Class::forName, "xxx");

*/public static  R uncheck(Function_WithExceptions function, T t) {

try { return function.apply(t); }

catch (Exception exception) { throwAsUnchecked(exception); return null; }

}@SuppressWarnings ("unchecked")private static  void throwAsUnchecked(Exception exception) throws E

{ throw (E)exception; }}

关于如何使用它的许多其他示例(静态导入之后)LambdaExceptionUtil):@Testpublic 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));

}@Testpublic void test_Function_with_checked_exceptions() throws ClassNotFoundException {

List classes1          = Stream.of("Object", "Integer", "String")

.map(rethrowFunction(className -> Class.forName("java.lang." + className)))

.collect(Collectors.toList());

List classes2          = Stream.of("java.lang.Object", "java.lang.Integer", "java.lang.String")

.map(rethrowFunction(Class::forName))

.collect(Collectors.toList());

}@Testpublic 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");

}

附注1:这个rethrow方法LambdaExceptionUtil上面的类可以毫无畏惧地使用,并且是可以在任何情况下使用..这在很大程度上要感谢用户@PaoloC,他帮助解决了最后一个问题:现在编译器将要求您添加抛出子句,这一切就好像您可以在Java 8流上本地抛出检查异常一样。

附注2:这个uncheck方法LambdaExceptionUtil上面的类是额外的方法,如果您不想使用它们,可以将它们安全地从类中删除。如果您确实使用了它们,请谨慎使用它们,而不是在了解以下用例、优点/缺点和限制之前:

·您可以使用uncheck方法,如果您正在调用一个方法,该方法实际上永远不能抛出它声明的异常。例如:新字符串(byteArr,“UTF-8”)抛出UnsuptedEncodingException,但是Java规范保证UTF-8始终存在。在这里,“抛出”声明是一个讨厌的问题,任何用最少的样板使其保持沉默的解决方案都是受欢迎的:String text = uncheck(() -> new String(byteArr, "UTF-8"));

·您可以使用uncheck方法,如果您正在实现一个严格的接口,而您没有添加抛出声明的选项,那么抛出异常是完全合适的。包装一个异常只是为了获得抛出它的特权,结果会产生带有虚假异常的堆栈跟踪,这些异常不会提供关于实际出错的信息。一个很好的例子是Runnable.run(),它不会抛出任何检查过的异常。

·无论如何,如果您决定使用uncheck方法,请注意抛出检查过的异常而没有抛出子句的两个后果:1)调用代码将无法按名称捕获它(如果您尝试,编译器会说:异常永远不会抛出在相应的try语句中)。它会出现气泡,并且可能会被某些“捕捉异常”或“捕捉Throwable”捕获,这可能是您想要的。2)这违反了“最不吃惊”的原则:它将不再足以抓住RuntimeException才能保证捕捉所有可能的异常。因此,我认为这不应该在框架代码中完成,而应该只在您完全控制的业务代码中完成。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值