欢迎访问 生活随笔!

生活随笔

当前位置: 首页 > 编程语言 > java >内容正文

java

异常作弊– Java 8 Lambdas

发布时间:2023/12/3 java 40 豆豆
生活随笔 收集整理的这篇文章主要介绍了 异常作弊– Java 8 Lambdas 小编觉得挺不错的,现在分享给大家,帮大家做个参考.

异常作弊– Java 8 Lambdas

撇开关于Checked vs Runtime异常的宗教辩论,有时由于库的构造不佳,处理Checked示例会使您发疯。

考虑一下您可能要编写的以下代码片段:

public void createTempFileForKey(String key) {Map<String, File> tempFiles = new ConcurrentHashMap<>();//does not compile because it throws an IOException!!tempFiles.computeIfAbsent(key, k -> File.createTempFile(key, ".tmp")); }

为了使其编译,您需要捕获使您留下此代码的异常:

public void createTempFileForKey(String key) {Map<String, File> tempFiles = new ConcurrentHashMap<>();tempFiles.computeIfAbsent(key, k -> {try {return File.createTempFile(key, ".tmp");}catch(IOException e) {e.printStackTrace();return null;}}); }

尽管可以编译,但是IOException已经有效地被吞没了。 应该通知此方法的用户已引发异常。

为了解决这个问题,您可以将IOException包装在通用的RuntimeException中,如下所示:

public void createTempFileForKey(String key) throws RuntimeException {Map<String, File> tempFiles = new ConcurrentHashMap<>();tempFiles.computeIfAbsent(key, k -> {try {return File.createTempFile(key, ".tmp");}catch(IOException e) {throw new RuntimeException(e);}}); }

这段代码确实抛出了一个Exception,但是没有抛出打算由该代码抛出的实际IOException。 那些只支持RuntimeExceptions的人可能会对这段代码感到满意,特别是如果可以改进解决方案以创建自定义的IORuntimeException的话。 尽管如此,大多数人还是以这种方式编写代码,他们希望他们的方法能够从File.createTempFile方法中抛出经过检查的IOException 。

这样做的自然方法有些复杂,看起来像这样:

public void createTempFileForKey(String key) throws IOException{Map<String, File> tempFiles = new ConcurrentHashMap<>();try {tempFiles.computeIfAbsent(key, k -> {try {return File.createTempFile(key, ".tmp");} catch (IOException e) {throw new RuntimeException(e);}});}catch(RuntimeException e){if(e.getCause() instanceof IOException){throw (IOException)e.getCause();}} }

从lambda内部,您必须捕获IOException,将其包装在RuntimeException中并抛出该RuntimeException。 Lambda必须捕获RuntimeException的包装并重新抛出IOException。 确实非常丑陋!

在理想的世界中,我们需要做的就是从lambda内抛出已检查的异常,而不必更改computeIfAbsent的声明。 换句话说,抛出检查异常,就好像它是运行时异常一样。 但是不幸的是,Java不允许我们这样做……

除非我们作弊,否则那不是! 这里有两种方法可以精确地执行我们想要的操作,即抛出检查异常,就好像它是运行时异常一样。

方法1 –使用泛型:

public static void main(String[] args){doThrow(new IOException());}static void doThrow(Exception e) {CheckedException.<RuntimeException> doThrow0(e);}static <E extends Exception>void doThrow0(Exception e) throws E {throw (E) e;}

请注意,我们已经创建并抛出了IOException,而没有在main方法中声明它。

方法2 –使用不安全:

public static void main(String[] args){getUnsafe().throwException(new IOException());}private static Unsafe getUnsafe(){try {Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");theUnsafe.setAccessible(true);return (Unsafe) theUnsafe.get(null);} catch (Exception e) {throw new AssertionError(e);}}

再次,我们设法抛出IOException而不在方法中声明它。

无论您喜欢哪种方法,我们现在都可以通过这种方式自由编写原始代码:

public void createTempFileForKey(String key) throws IOException{Map<String, File> tempFiles = new ConcurrentHashMap<>();tempFiles.computeIfAbsent(key, k -> {try {return File.createTempFile(key, ".tmp");} catch (IOException e) {throw doThrow(e);}});}private RuntimeException doThrow(Exception e){getUnsafe().throwException(e);return new RuntimeException();}private static Unsafe getUnsafe(){try {Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");theUnsafe.setAccessible(true);return (Unsafe) theUnsafe.get(null);} catch (Exception e) {throw new AssertionError(e);}}

doThrow()方法显然将封装在某些实用程序类中,从而使您的代码在createTempFileForKey()非常干净。

翻译自: https://www.javacodegeeks.com/2015/05/cheating-with-exceptions-java-8-lambdas.html

总结

以上是生活随笔为你收集整理的异常作弊– Java 8 Lambdas的全部内容,希望文章能够帮你解决所遇到的问题。

如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。