如何从Java 8流中抛出检查过的异常?

如何从Java 8流中抛出检查过的异常?

如何从Java 8流/lambda中抛出检查过的异常?

换句话说,我希望像这样编译代码:

public List<Class> getClasses() throws ClassNotFoundException {     

    List<Class> classes = 
        Stream.of("java.lang.Object", "java.lang.Integer", "java.lang.String")
              .map(className -> Class.forName(className))
              .collect(Collectors.toList());                  
    return classes;
    }

此代码不编译,因为Class.forName()以上抛出方法ClassNotFoundException,这是检查过的。

请注意,我不希望将选中的异常包装在运行时异常中,而是抛出已包装的未检查异常。我想抛出检查过的异常本身。,而不加丑陋try/catches去小溪。


呼啦一阵风
浏览 1944回答 3
3回答

慕的地10843

这,这个LambdaExceptionUtilHelper类允许您使用Java流中的任何检查异常,如下所示:Stream.of("java.lang.Object",&nbsp;"java.lang.Integer",&nbsp;"java.lang.String") &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.map(rethrowFunction(Class::forName)) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.collect(Collectors.toList());注Class::forName抛出ClassNotFoundException,也就是查证..流本身也抛出ClassNotFoundException,而不是一些未经检查的异常。public&nbsp;final&nbsp;class&nbsp;LambdaExceptionUtil&nbsp;{@FunctionalInterfacepublic&nbsp;interface&nbsp;Consumer_WithExceptions<T,&nbsp;E&nbsp;extends&nbsp;Exception>&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;void&nbsp;accept(T&nbsp;t)&nbsp;throws&nbsp;E; &nbsp;&nbsp;&nbsp;&nbsp;}@FunctionalInterfacepublic&nbsp;interface&nbsp;BiConsumer_WithExceptions<T,&nbsp;U,&nbsp;E&nbsp;extends&nbsp;Exception>&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;void&nbsp;accept(T&nbsp;t,&nbsp;U&nbsp;u)&nbsp;throws&nbsp;E; &nbsp;&nbsp;&nbsp;&nbsp;}@FunctionalInterfacepublic&nbsp;interface&nbsp;Function_WithExceptions<T,&nbsp;R,&nbsp;E&nbsp;extends&nbsp;Exception>&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;R&nbsp;apply(T&nbsp;t)&nbsp;throws&nbsp;E; &nbsp;&nbsp;&nbsp;&nbsp;}@FunctionalInterfacepublic&nbsp;interface&nbsp;Supplier_WithExceptions<T,&nbsp;E&nbsp;extends&nbsp;Exception>&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;T&nbsp;get()&nbsp;throws&nbsp;E; &nbsp;&nbsp;&nbsp;&nbsp;}@FunctionalInterfacepublic&nbsp;interface&nbsp;Runnable_WithExceptions<E&nbsp;extends&nbsp;Exception>&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;void&nbsp;run()&nbsp;throws&nbsp;E; &nbsp;&nbsp;&nbsp;&nbsp;}/**&nbsp;.forEach(rethrowConsumer(name&nbsp;->&nbsp;System.out.println(Class.forName(name))));&nbsp;or&nbsp;. &nbsp;&nbsp;&nbsp;&nbsp;forEach(rethrowConsumer(ClassNameUtil::println));&nbsp;*/public&nbsp;static&nbsp;<T,&nbsp;E&nbsp;extends&nbsp;Exception>&nbsp;Consumer<T> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rethrowConsumer(Consumer_WithExceptions<T,&nbsp;E>&nbsp;consumer)&nbsp;throws&nbsp;E&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;t&nbsp;->&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;try&nbsp;{&nbsp;consumer.accept(t);&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;catch&nbsp;(Exception&nbsp;exception)&nbsp;{&nbsp;throwAsUnchecked(exception);&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}; &nbsp;&nbsp;&nbsp;&nbsp;}public&nbsp;static&nbsp;<T,&nbsp;U,&nbsp;E&nbsp;extends&nbsp;Exception>&nbsp;BiConsumer<T,&nbsp;U>&nbsp;rethrowBiConsumer(BiConsumer_WithExceptions<T,&nbsp;U,&nbsp;E>&nbsp;biConsumer)&nbsp;throws&nbsp;E&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;(t,&nbsp;u)&nbsp;->&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;try&nbsp;{&nbsp;biConsumer.accept(t,&nbsp;u);&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;catch&nbsp;(Exception&nbsp;exception)&nbsp;{&nbsp;throwAsUnchecked(exception);&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}; &nbsp;&nbsp;&nbsp;&nbsp;}/**&nbsp;.map(rethrowFunction(name&nbsp;->&nbsp;Class.forName(name)))&nbsp;or&nbsp;.map(rethrowFunction(Class::forName))&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;*/public&nbsp;static&nbsp;<T,&nbsp;R,&nbsp;E&nbsp;extends&nbsp;Exception>&nbsp;Function<T,&nbsp;R>&nbsp;rethrowFunction(Function_WithExceptions<T,&nbsp;R,&nbsp;E>&nbsp;function)&nbsp;throws&nbsp;E&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;t&nbsp;->&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;try&nbsp;{&nbsp;return&nbsp;function.apply(t);&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;catch&nbsp;(Exception&nbsp;exception)&nbsp;{&nbsp;throwAsUnchecked(exception);&nbsp;return&nbsp;null;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}; &nbsp;&nbsp;&nbsp;&nbsp;}/**&nbsp;rethrowSupplier(()&nbsp;->&nbsp;new&nbsp;StringJoiner(new&nbsp;String(new&nbsp;byte[]{77,&nbsp;97,&nbsp;114,&nbsp;107},&nbsp;"UTF-8"))),&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;*/public&nbsp;static&nbsp;<T,&nbsp;E&nbsp;extends&nbsp;Exception>&nbsp;Supplier<T>&nbsp;rethrowSupplier(Supplier_WithExceptions<T,&nbsp;E>&nbsp;function)&nbsp;throws&nbsp;E&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;()&nbsp;->&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;try&nbsp;{&nbsp;return&nbsp;function.get();&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;catch&nbsp;(Exception&nbsp;exception)&nbsp;{&nbsp;throwAsUnchecked(exception);&nbsp;return&nbsp;null;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}; &nbsp;&nbsp;&nbsp;&nbsp;}/**&nbsp;uncheck(()&nbsp;->&nbsp;Class.forName("xxx"));&nbsp;*/public&nbsp;static&nbsp;void&nbsp;uncheck(Runnable_WithExceptions&nbsp;t) &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;try&nbsp;{&nbsp;t.run();&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;catch&nbsp;(Exception&nbsp;exception)&nbsp;{&nbsp;throwAsUnchecked(exception);&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;}/**&nbsp;uncheck(()&nbsp;->&nbsp;Class.forName("xxx"));&nbsp;*/public&nbsp;static&nbsp;<R,&nbsp;E&nbsp;extends&nbsp;Exception>&nbsp;R&nbsp;uncheck(Supplier_WithExceptions<R,&nbsp;E>&nbsp;supplier) &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;try&nbsp;{&nbsp;return&nbsp;supplier.get();&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;catch&nbsp;(Exception&nbsp;exception)&nbsp;{&nbsp;throwAsUnchecked(exception);&nbsp;return&nbsp;null;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;}/**&nbsp;uncheck(Class::forName,&nbsp;"xxx");&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;*/public&nbsp;static&nbsp;<T,&nbsp;R,&nbsp;E&nbsp;extends&nbsp;Exception>&nbsp;R&nbsp;uncheck(Function_WithExceptions<T,&nbsp;R,&nbsp;E>&nbsp;function,&nbsp;T&nbsp;t)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;try&nbsp;{&nbsp;return&nbsp;function.apply(t);&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;catch&nbsp;(Exception&nbsp;exception)&nbsp;{&nbsp;throwAsUnchecked(exception);&nbsp;return&nbsp;null;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;}@SuppressWarnings&nbsp;("unchecked")private&nbsp;static&nbsp;<E&nbsp;extends&nbsp;Throwable>&nbsp;void&nbsp;throwAsUnchecked(Exception&nbsp;exception)&nbsp;throws&nbsp;E&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;throw&nbsp;(E)exception;&nbsp;}}关于如何使用它的许多其他示例(静态导入之后)LambdaExceptionUtil):@Testpublic&nbsp;void&nbsp;test_Consumer_with_checked_exceptions()&nbsp;throws&nbsp;IllegalAccessException&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;Stream.of("java.lang.Object",&nbsp;"java.lang.Integer",&nbsp;"java.lang.String") &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.forEach(rethrowConsumer(className&nbsp;->&nbsp;System.out.println(Class.forName(className)))); &nbsp;&nbsp;&nbsp;&nbsp;Stream.of("java.lang.Object",&nbsp;"java.lang.Integer",&nbsp;"java.lang.String") &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.forEach(rethrowConsumer(System.out::println)); &nbsp;&nbsp;&nbsp;&nbsp;}@Testpublic&nbsp;void&nbsp;test_Function_with_checked_exceptions()&nbsp;throws&nbsp;ClassNotFoundException&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;List<Class>&nbsp;classes1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;=&nbsp;Stream.of("Object",&nbsp;"Integer",&nbsp;"String") &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.map(rethrowFunction(className&nbsp;->&nbsp;Class.forName("java.lang."&nbsp;+&nbsp;className))) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.collect(Collectors.toList()); &nbsp;&nbsp;&nbsp;&nbsp;List<Class>&nbsp;classes2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;=&nbsp;Stream.of("java.lang.Object",&nbsp;"java.lang.Integer",&nbsp;"java.lang.String") &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.map(rethrowFunction(Class::forName)) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.collect(Collectors.toList()); &nbsp;&nbsp;&nbsp;&nbsp;}@Testpublic&nbsp;void&nbsp;test_Supplier_with_checked_exceptions()&nbsp;throws&nbsp;ClassNotFoundException&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;Collector.of( &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rethrowSupplier(()&nbsp;->&nbsp;new&nbsp;StringJoiner(new&nbsp;String(new&nbsp;byte[]{77,&nbsp;97,&nbsp;114,&nbsp;107},&nbsp;"UTF-8"))), &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;StringJoiner::add,&nbsp;StringJoiner::merge,&nbsp;StringJoiner::toString); &nbsp;&nbsp;&nbsp;&nbsp;}@Test&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;void&nbsp;test_uncheck_exception_thrown_by_method()&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;Class&nbsp;clazz1&nbsp;=&nbsp;uncheck(()&nbsp;->&nbsp;Class.forName("java.lang.String")); &nbsp;&nbsp;&nbsp;&nbsp;Class&nbsp;clazz2&nbsp;=&nbsp;uncheck(Class::forName,&nbsp;"java.lang.String"); &nbsp;&nbsp;&nbsp;&nbsp;}@Test&nbsp;(expected&nbsp;=&nbsp;ClassNotFoundException.class)public&nbsp;void&nbsp;test_if_correct_exception_is_still_thrown_by_method()&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;Class&nbsp;clazz3&nbsp;=&nbsp;uncheck(Class::forName,&nbsp;"INVALID"); &nbsp;&nbsp;&nbsp;&nbsp;}附注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才能保证捕捉所有可能的异常。因此,我认为这不应该在框架代码中完成,而应该只在您完全控制的业务代码中完成。参考资料:http:/www.Philandstuff.com/2012/04/28/http:/www.mail-Archive.com/javaposse@googlegroups.com/msg05984.html项目Lombok注释:@SneakyThrowBrian Goetz的意见(反对)如下:如何从Java 8流中抛出检查过的异常?https:/SofareEnginering.stackExchangee.com/问询/225931/变通-for-java检查异常?newreg=ddf0dd15e8174af8ba52e091cf85688e&nbsp;*

慕桂英4014372

你不能安全地这么做。你可以作弊,但你的程序被破坏了,这不可避免地会回来咬人(应该是你,但我们的欺骗往往会对别人造成打击)。这里有一个稍微安全的方法(但我还是不推荐这样做)。class&nbsp;WrappedException&nbsp;extends&nbsp;RuntimeException&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;Throwable&nbsp;cause; &nbsp;&nbsp;&nbsp;&nbsp;WrappedException(Throwable&nbsp;cause)&nbsp;{&nbsp;this.cause&nbsp;=&nbsp;cause;&nbsp;}}static&nbsp;WrappedException&nbsp;throwWrapped(Throwable&nbsp;t)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;throw&nbsp;new&nbsp;WrappedException(t);}try&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;source.stream() &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.filter(e&nbsp;->&nbsp;{&nbsp;...&nbsp;try&nbsp;{&nbsp;...&nbsp;}&nbsp;catch&nbsp;(IOException&nbsp;e)&nbsp;{&nbsp;throwWrapped(e);&nbsp;}&nbsp;...&nbsp;}) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;...}catch&nbsp;(WrappedException&nbsp;w)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;throw&nbsp;(IOException)&nbsp;w.cause;}在这里,您要做的是捕获lambda中的异常,从流管道中抛出一个信号,该信号表示计算异常失败,捕获信号,并对该信号执行操作以抛出潜在的异常。关键是,您总是捕获合成异常,而不是允许检查的异常泄漏而不声明该异常被抛出。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java