网站工程师是做什么的,访问的网页正在升级中,网站黑链,杭州产品设计公司有哪些java 8 lambda异常作弊– Java 8 Lambdas 撇开关于Checked vs Runtime异常的宗教辩论#xff0c;有时由于库的构造不佳#xff0c;处理Checked示例会使您发疯。 考虑一下您可能要编写的以下代码片段#xff1a; public void createTempFileForKey(String key) {MapStr… java 8 lambda 异常作弊– Java 8 Lambdas 撇开关于Checked vs Runtime异常的宗教辩论有时由于库的构造不佳处理Checked示例会使您发疯。 考虑一下您可能要编写的以下代码片段 public void createTempFileForKey(String key) {MapString, 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) {MapString, 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 {MapString, 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{MapString, 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 Exceptionvoid 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{MapString, 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.htmljava 8 lambda