lambda表达式一定要在内部捕获受检异常?
场景
以调用java.util.ArrayList#forEach方法为例,用不同的lambda表达式重写该Consumer接口。
RuntimeException
list中有两个元素,调用forEach遍历,使用lambda重写Consumer接口,抛出不受检异常RuntimeException。
下面代码编译通过。
@Test
public void listForeachRuntimeExceptionTest() {
final List<Integer> list = new ArrayList<>(2);
list.add(1);
list.add(2);
list.forEach(
i -> {
System.out.println(i);
throw new RuntimeException();
});
}
受检异常
lambda内部抛出IOException
对上面的代码做一点修改,修改抛出的异常为IOException:
@Test
public void listForeachCheckedExceptionTest() {
final List<Integer> list = new ArrayList<>(2);
list.add(1);
list.add(2);
list.forEach(
i -> {
System.out.println(i);
throw new IOException();
});
}
如此编译会报错,因为IOException是受检异常,需要被捕获或抛到外层处理。
外层方法抛出该异常
将代码修改为在外层方法抛出该异常,编译也是会报错的,如下代码:
@Test
public void listForeachCheckedExceptionTest() throws IOException {
final List<Integer> list = new ArrayList<>(2);
list.add(1);
list.add(2);
list.forEach(
i -> {
System.out.println(i);
throw new IOException();
});
}
这是由于java.util.function.Consumer#accept方法签名没有声明抛出IOException,并且java.util.ArrayList#forEach方法也没有对异常的处理。所以导致lambda表达式重写后的方法签名也是没有声明有异常抛出的。
java.util.function.Consumer#accept源码
@FunctionalInterface
public interface Consumer<T> {
/**
* Performs this operation on the given argument.
*
* @param t the input argument
*/
void accept(T t);
......
}
内部捕获
所以要想编译不报错,上面代码只能在lambda内部捕获该异常:
@Test
public void listForeachCheckedExceptionTest() {
final List<Integer> list = new ArrayList<>(2);
list.add(1);
list.add(2);
list.forEach(
i -> {
System.out.println(i);
try {
throw new IOException();
} catch (IOException e) {
e.printStackTrace();
}
});
}
小结
由于java.util.ArrayList#forEach的函数式形参java.util.function.Consumer类,它的accept方法签名没有声明抛出IOException,所以内部的受检异常IOException必须捕获。
自定义函数式接口(声明受检异常)
难道所有的lambda表达式,遇到受检异常就必须都在内部捕获吗?
当然不是。
受检异常函数式接口
为了方便后续测试,自定义一个接口,只有一个方法action,方法签名带有受检异常(IOException)。
/**
* @author https://www.cnblogs.com/theRhyme/
*/
@FunctionalInterface
public interface CheckedExceptionAction<T> {
void action(T t) throws IOException;
}
自定义forEach接口声明异常
这里自定义一个接口,声明的是抛出受检异常IOException。
/**
* @author https://www.cnblogs.com/theRhyme/
*/
public interface MyIterable<T> {
void forEach(CheckedExceptionAction<? super T> action) throws IOException;
}
自定义forEach实现
自定义MyList,为了方便测试,这里只有add和forEach方法。
由于是重写的上面自定义接口的forEach方法,方法声明自然也有throws IOException,这里的声明异常是为了将CheckedExceptionAction#action产生的异常抛出去,当然也可以在自定义的forEach中捕获。
/**
* @author https://www.cnblogs.com/theRhyme/
*/
public class MyList<T> implements RandomAccess, MyIterable<T> {
private List<T> list;
public MyList() {
list = new ArrayList<>();
}
public boolean add(T t) {
return list.add(t);
}
@Override
public void forEach(CheckedExceptionAction<? super T> action) throws IOException {
for (T t : list) {
action.action(t);
}
}
}
测试
添加两个元素,并且在forEach中抛出的受检异常IOException,代码编译通过。
所以当forEach中的函数式形参CheckedExceptionAction声明了对应的受检异常,则lambda表达式内部不用捕获该异常。
/**
* @author https://www.cnblogs.com/theRhyme/
*/
public class Main {
public static void main(String[] args) throws IOException {
final MyList<Integer> myList = new MyList<>();
myList.add(1);
myList.add(2);
myList.forEach(i -> {
System.out.println(i);
throw new IOException();
});
}
}
受检异常与不受检异常
受检异常(checkedException),又叫做编译时异常,指的是代码编译期间,必须由编程人员手动处理(try-catch捕获或者throws抛出)的异常,否则代码报错,例如IOException。
不受检异常(uncheckedException),又叫运行时异常(RuntimeException),指的是代码运行时出现的异常,比如ArrayIndexOutOfBoundsException,ClassCastException。
总结
在JDK源码中,像java.util.ArrayList#forEach一样的函数式形参Consumer#accept的方法声明中,没有声明对应的受检异常,所以传递lambda表达式内部可以抛出不受检异常RuntimeException,但是对于受检异常(如**IOException**)只能在内部捕获该异常;
如果函数式形参声明了对应的受检异常,则lambda表达式内部可以抛出对应的受检异常,即不用在内部捕获;
函数式编程本质就是重写方法,返回对象实例的过程,既然是重写方法,原方法未声明异常,自然重写的方法就不能声明异常;
Lambda表达式内部是否需要捕获受检异常,实际上与Lambda表达式重写的方法有关。
lambda表达式一定要在内部捕获受检异常?的更多相关文章
- Lambda 表达式[MSDN]
Lambda 表达式是一种可用于创建委托或表达式目录树类型的匿名函数. 通过使用 lambda 表达式,可以写入可作为参数传递或作为函数调用值返回的本地函数.Lambda 表达式对于编写 LINQ 查 ...
- Lambda 表达式(C# 编程指南) 微软microsoft官方说明
Visual Studio 2013 其他版本 Lambda 表达式是一种可用于创建委托或表达式目录树类型的匿名函数. 通过使用 lambda 表达式,可以写入可作为参数传递或作为函数调用值返回的本地 ...
- lambda函数、lambda表达式
C++11 新特性:Lambda 表达式 豆子 2012年5月15日 C++ 10条评论 参考文章:https://blogs.oracle.com/pcarlini/entry/c_1x_tidbi ...
- 深入探索Java 8 Lambda表达式
2014年3月,Java 8发布,Lambda表达式作为一项重要的特性随之而来.或许现在你已经在使用Lambda表达式来书写简洁灵活的代码.比如,你可以使用Lambda表达式和新增的流相关的API,完 ...
- Cocos2d-x v3.0 新的事件调度方法 lambda表达式的使用
欢迎添� Cocos2d-x 交流群: 193411763 转载请注明原文出处:http://blog.csdn.net/u012945598/article/details/24603251 Coc ...
- C++11中新特性之:lambda 表达式
首先摆出Lambda表达式语法 lambda-expression: lambda-introducer lambda-declaratoropt compound-statementlambda-i ...
- [Java 8] (5) 使用Lambda表达式进行设计
使用Lambda表达式进行设计 在前面的几篇文章中,我们已经见识到了Lambda表达式是怎样让代码变的更加紧凑和简洁的. 这一篇文章主要会介绍Lambda表达式怎样改变程序的设计.怎样让程序变的更加轻 ...
- Lambda 表达式的示例-来源(MSDN)
本文演示如何在你的程序中使用 lambda 表达式. 有关 lambda 表达式的概述,请参阅 C++ 中的 Lambda 表达式. 有关 lambda 表达式结构的详细信息,请参阅 Lambda 表 ...
- (zz)Lambda 表达式(C# 编程指南)
https://msdn.microsoft.com/zh-cn/library/bb397687.aspx Lambda 表达式是一种可用于创建委托或表达式目录树类型的匿名函数.通过使用 lambd ...
- C++教程之lambda表达式一
什么是Lambda? C++ 11增加了一个很重要的特性--Lambda表达式.营里(戴维营)的兄弟都对Objective-C很熟悉,很多人多block情有独钟,将各种回调函数.代理通通都用它来实现. ...
随机推荐
- Linux系列:如何用perf跟踪.NET程序的mmap泄露
一:背景 1. 讲故事 如何跟踪.NET程序的mmap泄露,这个问题困扰了我差不多一年的时间,即使在官方的github库中也找不到切实可行的方案,更多海外大佬只是推荐valgrind这款工具,但这款工 ...
- js技术之“input输入框转成下拉框,且保留可输入能力”
一.jsp前端控件 <td class="form-label"> <label class="control-label">供货商货号 ...
- 在rk3588上部署InternVL系列
在rk3588上部署InternVL2-1B 准备 首先要在hf上下载InternVL2-1B的模型传送门(镜像) git clone https://hf-mirror.com/OpenGVLab/ ...
- SQL 优化 - 多层嵌套逻辑先行
近段时间就是忙得不亦乐乎, 一个人搞项目, 中途几经崩溃, 一个是业务方案有问题, 被带跑偏了整整一周, 最后尝试去挑战, 才重新回到正轨. 然后就是自己搞崩盘, sql 这块的处理, 嵌套写太深了, ...
- 神经网络-反向传播BP算法推导
还是用前向算法的图, 然后仔细一看分类输出, 发现好像错了, 这该如何去反向修改权值呢? 因其是网络结构, 改变一点, 必然会引起一连串的改动, 这个过程, 如何来描述呢? 数学推导 声明变量 首先, ...
- 私人问卷收集系统-Surveyking问卷收集系统
前言 但凡提及问卷收集系统,问卷星与腾讯问卷通常都为大家首选问卷调查系统. 担心数据安全,海量问卷管理不便,工作流创建困难?快速部署自有问卷调查系统开始你的问卷调查之旅. 无论是问卷调查,考试系统,公 ...
- RPC实战与核心原理之流量回放
流量回放:保障业务技术升级的神器 回顾 时钟轮在 RPC 中的应用,核心原理就一个关键字"分而治之",我们可以把它用在任何需要高效处理大量定时任务的场景中,最具有代表性的就是在高并 ...
- pyqt点击右上角关闭界面但子线程仍在运行
现象: 通过右上角的叉关闭图形界面后,程序运行的子线程却不会被自动关闭,依然留存在系统中 原因: 子线程没有正确关闭 解决方法: 1.将子线程设置成守护线程 self.your_thread = th ...
- 跨平台之 KMP / KMM 详解
任何事情,急于求成都是幼稚的幻想,急于求成的结果一定是不成,对此不应该有任何怀疑. 一. KMP 和 Compose Multiplatform 摘要:减少为不同平台编写和维护相同业务逻辑代码所花费的 ...
- DBA必备神器:让Oracle关库不再心惊胆战!
我们的文章会在微信公众号"Oracle恢复实录"和博客网站同步更新,欢迎关注收藏.也欢迎大家转载,但请在文章开始处标注文章出处,谢谢! 由于博客中包含大量代码,建议通过网页浏览以获 ...