java 8 lambda表达式中的异常处理

简介

java 8中引入了lambda表达式,lambda表达式可以让我们的代码更加简介,业务逻辑更加清晰,但是在lambda表达式中使用的Functional Interface并没有很好的处理异常,因为JDK提供的这些Functional Interface通常都是没有抛出异常的,这意味着需要我们自己手动来处理异常。

因为异常分为Unchecked Exception和checked Exception,我们分别来讨论。

处理Unchecked Exception

Unchecked exception也叫做RuntimeException,出现RuntimeException通常是因为我们的代码有问题。RuntimeException是不需要被捕获的。也就是说如果有RuntimeException,没有捕获也可以通过编译。

我们看一个例子:

  1. List<Integer> integers = Arrays.asList(1,2,3,4,5);
  2. integers.forEach(i -> System.out.println(1 / i));

这个例子是可以编译成功的,但是上面有一个问题,如果list中有一个0的话,就会抛出ArithmeticException。

虽然这个是一个Unchecked Exception,但是我们还是想处理一下:

  1. integers.forEach(i -> {
  2. try {
  3. System.out.println(1 / i);
  4. } catch (ArithmeticException e) {
  5. System.err.println(
  6. "Arithmetic Exception occured : " + e.getMessage());
  7. }
  8. });

上面的例子我们使用了try,catch来处理异常,简单但是破坏了lambda表达式的最佳实践。代码变得臃肿。

我们将try,catch移到一个wrapper方法中:

  1. static Consumer<Integer> lambdaWrapper(Consumer<Integer> consumer) {
  2. return i -> {
  3. try {
  4. consumer.accept(i);
  5. } catch (ArithmeticException e) {
  6. System.err.println(
  7. "Arithmetic Exception occured : " + e.getMessage());
  8. }
  9. };
  10. }

则原来的调用变成这样:

  1. integers.forEach(lambdaWrapper(i -> System.out.println(1 / i)));

但是上面的wrapper固定了捕获ArithmeticException,我们再将其改编成一个更通用的类:

  1. static <T, E extends Exception> Consumer<T>
  2. consumerWrapperWithExceptionClass(Consumer<T> consumer, Class<E> clazz) {
  3. return i -> {
  4. try {
  5. consumer.accept(i);
  6. } catch (Exception ex) {
  7. try {
  8. E exCast = clazz.cast(ex);
  9. System.err.println(
  10. "Exception occured : " + exCast.getMessage());
  11. } catch (ClassCastException ccEx) {
  12. throw ex;
  13. }
  14. }
  15. };
  16. }

上面的类传入一个class,并将其cast到异常,如果能cast,则处理,否则抛出异常。

这样处理之后,我们这样调用:

  1. integers.forEach(
  2. consumerWrapperWithExceptionClass(
  3. i -> System.out.println(1 / i),
  4. ArithmeticException.class));

处理checked Exception

checked Exception是必须要处理的异常,我们还是看个例子:

  1. static void throwIOException(Integer integer) throws IOException {
  2. }
  1. List<Integer> integers = Arrays.asList(1, 2, 3, 4, 5);
  2. integers.forEach(i -> throwIOException(i));

上面我们定义了一个方法抛出IOException,这是一个checked Exception,需要被处理,所以在下面的forEach中,程序会编译失败,因为没有处理相应的异常。

最简单的办法就是try,catch住,如下所示:

  1. integers.forEach(i -> {
  2. try {
  3. throwIOException(i);
  4. } catch (IOException e) {
  5. throw new RuntimeException(e);
  6. }
  7. });

当然,这样的做法的坏处我们在上面已经讲过了,同样的,我们可以定义一个新的wrapper方法:

  1. static <T> Consumer<T> consumerWrapper(
  2. ThrowingConsumer<T, Exception> throwingConsumer) {
  3. return i -> {
  4. try {
  5. throwingConsumer.accept(i);
  6. } catch (Exception ex) {
  7. throw new RuntimeException(ex);
  8. }
  9. };
  10. }

我们这样调用:

  1. integers.forEach(consumerWrapper(i -> throwIOException(i)));

我们也可以封装一下异常:

  1. static <T, E extends Exception> Consumer<T> consumerWrapperWithExceptionClass(
  2. ThrowingConsumer<T, E> throwingConsumer, Class<E> exceptionClass) {
  3. return i -> {
  4. try {
  5. throwingConsumer.accept(i);
  6. } catch (Exception ex) {
  7. try {
  8. E exCast = exceptionClass.cast(ex);
  9. System.err.println(
  10. "Exception occured : " + exCast.getMessage());
  11. } catch (ClassCastException ccEx) {
  12. throw new RuntimeException(ex);
  13. }
  14. }
  15. };
  16. }

然后这样调用:

  1. integers.forEach(consumerWrapperWithExceptionClass(
  2. i -> throwIOException(i), IOException.class));

总结

本文介绍了如何在lambda表达式中处理checked和unchecked异常,希望能给大家一些帮助。

本文的例子https://github.com/ddean2009/learn-java-streams/tree/master/lambda-exception

欢迎关注我的公众号:程序那些事,更多精彩等着您!

更多内容请访问 www.flydean.com

java 8 lambda表达式中的异常处理的更多相关文章

  1. Java 8 Lambda表达式

    Java 8 Lambda表达式探险 http://www.cnblogs.com/feichexia/archive/2012/11/15/Java8_LambdaExpression.html 为 ...

  2. 深入浅出 Java 8 Lambda 表达式

    摘要:此篇文章主要介绍 Java8 Lambda 表达式产生的背景和用法,以及 Lambda 表达式与匿名类的不同等.本文系 OneAPM 工程师编译整理. Java 是一流的面向对象语言,除了部分简 ...

  3. Java 8 Lambda表达式10个示例【存】

    PS:不能完全参考文章的代码,请参考这个文件http://files.cnblogs.com/files/AIThink/Test01.zip 在Java 8之前,如果想将行为传入函数,仅有的选择就是 ...

  4. Java SE 8 for the Really Impatient读书笔记——Java 8 Lambda表达式

    1. lambda表达式的语法 lambda表达式是一种没有名字的函数,它拥有函数体和参数. lambda表达式的语法十分简单:参数->主体.通过->来分离参数和主体. 1.1 参数 la ...

  5. Java 8 Lambda 表达式

    Lambda 是啥玩意 简单来说,Lambda 就是一个匿名的方法,就这样,没啥特别的.它采用一种非常简洁的方式来定义方法.当你想传递可复用的方法片段时,匿名方法非常有用.例如,将一个方法传递给另外一 ...

  6. java 8 Lambda表达式(翻译自Stackoverflow)

    (原文链接)Lambda只能作用于一个只有一个抽象方法的函数式接口(Function Interface),不过函数式接口可以有任意数量default或static修饰的方法(因此,它们有时也被当做单 ...

  7. Java 8 Lambda 表达式(一)

    Java 8 新特性 Lambda 表达式,也可称为闭包,它是推动 Java 8 发布的最重要新特性. Lambda 允许把函数作为一个方法的参数(函数作为参数传递进方法中). 使用 Lambda 表 ...

  8. 聊聊Java 8 Lambda 表达式

      早在2014年oracle发布了jdk 8,在里面增加了lambda模块.于是java程序员们又多了一种新的编程方式:函数式编程,也就是lambda表达式.我自己用lambda表达式也差不多快4年 ...

  9. Java 8 lambda表达式示例

    例1.用lambda表达式实现Runnable 我开始使用Java 8时,首先做的就是使用lambda表达式替换匿名类,而实现Runnable接口是匿名类的最好示例.看一下Java 8之前的runna ...

随机推荐

  1. PTA数据结构与算法题目集(中文) 7-32

    PTA数据结构与算法题目集(中文)  7-32 7-32 哥尼斯堡的“七桥问题” (25 分)   哥尼斯堡是位于普累格河上的一座城市,它包含两个岛屿及连接它们的七座桥,如下图所示. 可否走过这样的七 ...

  2. PTA数据结构与算法题目集(中文) 7-9

    PTA数据结构与算法题目集(中文)  7-9 7-9 旅游规划 (25 分)   有了一张自驾旅游路线图,你会知道城市间的高速公路长度.以及该公路要收取的过路费.现在需要你写一个程序,帮助前来咨询的游 ...

  3. python--爬虫之JSON于JsonPath

    JSON json的引入 在python中json作为一个内建库不需要额外安装,只需要使用import json执行引入 json模块的功能 在python中json模块提供了四个功能:dumps.d ...

  4. Tcl编程第三天,数学运算

    1.tcl语言没有自己的数学计算,如果想要使用数学公式,必须得用C语言的库.使用方法如下. #!/usr/bin/tclsh set value [expr 8/5] puts $value set ...

  5. Python常见数据结构-Set集合

    集合基本特点 集合是无序的,且集合内无重复值. 集合不支持索引和切片 集合常见操作及方法 s1 = {1,2,3} s2 = {2,3,4} s1.add(4) #.add()方法添加一个元素 s1. ...

  6. Array(数组)对象-->pop() 方法

    1.定义和用法 pop() 方法用于删除数组的最后一个元素并返回删除的元素. 语法: array.pop() 注意:此方法改变数组的长度! 举例: var arr = [1,2,3,4,5]; con ...

  7. Python爬虫 ---scrapy框架初探及实战

    目录 Scrapy框架安装 操作环境介绍 安装scrapy框架(linux系统下) 检测安装是否成功 Scrapy框架爬取原理 Scrapy框架的主体结构分为五个部分: 它还有两个可以自定义下载功能的 ...

  8. poj3585 Accumulation Degree(换根dp)

    传送门 换根dp板子题(板子型选手 题意: 一棵树确定源点和汇点找到最大的流量(拿出一整套最大瘤板子orz ; int head[maxn],tot; struct node { int nt,to; ...

  9. Golang源码分析之目录详解

    开源项目「go home」聚焦Go语言技术栈与面试题,以协助Gopher登上更大的舞台,欢迎go home~ 导读 学习Go语言源码的第一步就是了解先了解它的目录结构,你对它的源码目录了解多少呢? 目 ...

  10. Pytest系列(21)- allure的特性,@allure.description()、@allure.title()的详细使用

    如果你还想从头学起Pytest,可以看看这个系列的文章哦! https://www.cnblogs.com/poloyy/category/1690628.html 前言 前面介绍了两种allure的 ...