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

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

目录



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,没有捕获也可以通过编译。


我们看一个例子:


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


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


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


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


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


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


static Consumer<Integer> lambdaWrapper(Consumer<Integer> consumer) {
        return i -> {
            try {
                consumer.accept(i);
            } catch (ArithmeticException e) {
                System.err.println(
                        "Arithmetic Exception occured : " + e.getMessage());
            }
        };
    }


则原来的调用变成这样:


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


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


static <T, E extends Exception> Consumer<T>
    consumerWrapperWithExceptionClass(Consumer<T> consumer, Class<E> clazz) {
        return i -> {
            try {
                consumer.accept(i);
            } catch (Exception ex) {
                try {
                    E exCast = clazz.cast(ex);
                    System.err.println(
                            "Exception occured : " + exCast.getMessage());
                } catch (ClassCastException ccEx) {
                    throw ex;
                }
            }
        };
    }


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

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


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


处理checked Exception


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


static void throwIOException(Integer integer) throws IOException {
    }


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


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


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


integers.forEach(i -> {
            try {
                throwIOException(i);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        });


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


static <T> Consumer<T> consumerWrapper(
            ThrowingConsumer<T, Exception> throwingConsumer) {
        return i -> {
            try {
                throwingConsumer.accept(i);
            } catch (Exception ex) {
                throw new RuntimeException(ex);
            }
        };
    }


我们这样调用:


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


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


static <T, E extends Exception> Consumer<T> consumerWrapperWithExceptionClass(
            ThrowingConsumer<T, E> throwingConsumer, Class<E> exceptionClass) {
        return i -> {
            try {
                throwingConsumer.accept(i);
            } catch (Exception ex) {
                try {
                    E exCast = exceptionClass.cast(ex);
                    System.err.println(
                            "Exception occured : " + exCast.getMessage());
                } catch (ClassCastException ccEx) {
                    throw new RuntimeException(ex);
                }
            }
        };
    }


然后这样调用:


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


总结


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


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

相关文章
|
14天前
|
Java 编译器
探索Java中的异常处理机制
【10月更文挑战第35天】在Java的世界中,异常是程序运行过程中不可避免的一部分。本文将通过通俗易懂的语言和生动的比喻,带你了解Java中的异常处理机制,包括异常的类型、如何捕获和处理异常,以及如何在代码中有效地利用异常处理来提升程序的健壮性。让我们一起走进Java的异常世界,学习如何优雅地面对和解决问题吧!
|
2天前
|
安全 Java 程序员
Java中的异常处理:从新手到专家
在Java编程的世界里,异常处理是每个开发者必须面对的挑战。本文将带你从基础的异常概念出发,逐步深入到高级处理技巧,让你在遇到代码中的“意外”时,能够从容应对,甚至化险为夷。
|
7天前
|
Java 数据库连接 开发者
Java中的异常处理:从基础到高级
【10月更文挑战第42天】在Java的世界中,异常处理是维护程序稳定性和健壮性的关键。本文将带你深入了解Java的异常处理机制,从基本的try-catch语句出发,逐步探索更复杂的异常处理策略。我们将通过实际代码示例来演示如何捕获和处理异常,以及如何自定义异常类型来满足特定需求。无论你是Java新手还是有经验的开发者,这篇文章都将帮助你更好地理解和应用Java的异常处理。
|
12天前
|
Java
探索Java中的Lambda表达式
【10月更文挑战第37天】本文将带你深入理解Java的Lambda表达式,从基础语法到高级特性,通过实例讲解其在函数式编程中的应用。我们还将探讨Lambda表达式如何简化代码、提高开发效率,并讨论其在实际项目中的应用。
|
14天前
|
Java 开发者
Java中的异常处理:从基础到高级
【10月更文挑战第35天】在Java的世界里,异常处理是维护程序健壮性的关键。本文将深入浅出地探讨Java的异常处理机制,从基本的try-catch语句到自定义异常类的实现,带领读者理解并掌握如何在Java中优雅地处理错误和异常。我们将通过实际代码示例,展示如何捕获、处理以及预防潜在的运行时错误,确保程序即使在面临意外情况时也能保持稳定运行。
31 7
|
15天前
|
Java API
Java中的Lambda表达式与函数式编程####
【10月更文挑战第29天】 本文将深入探讨Java中Lambda表达式的实现及其在函数式编程中的应用。通过对比传统方法,我们将揭示Lambda如何简化代码、提高可读性和维护性。文章还将展示一些实际案例,帮助读者更好地理解和应用Lambda表达式。 ####
|
15天前
|
JSON 自然语言处理 Java
这款轻量级 Java 表达式引擎,真不错!
AviatorScript 是一个高性能、轻量级的脚本语言,基于 JVM(包括 Android 平台)。它支持数字、字符串、正则表达式、布尔值等基本类型,以及所有 Java 运算符。主要特性包括函数式编程、大整数和高精度运算、完整的脚本语法、丰富的内置函数和自定义函数支持。适用于规则判断、公式计算、动态脚本控制等场景。
|
13天前
|
Java 数据库连接 开发者
Java中的异常处理机制及其最佳实践####
在本文中,我们将探讨Java编程语言中的异常处理机制。通过深入分析try-catch语句、throws关键字以及自定义异常的创建与使用,我们旨在揭示如何有效地管理和响应程序运行中的错误和异常情况。此外,本文还将讨论一些最佳实践,以帮助开发者编写更加健壮和易于维护的代码。 ####
|
17天前
|
Java
Java 异常处理下篇:11 个异常处理最佳实践
本文深入探讨了 Java 异常处理的最佳实践,包括早抛出晚捕获、只捕获可处理的异常、不要忽略捕获的异常、抛出具体检查性异常、正确包装自定义异常、记录或抛出异常但不同时执行、避免在 `finally` 块中抛出异常、避免使用异常进行流程控制、使用模板方法处理重复的 `try-catch`、尽量只抛出与方法相关的异常以及异常处理后清理资源。通过遵循这些实践,可以提高代码的健壮性和可维护性。
|
19天前
|
Java API 开发者
Java中的Lambda表达式与函数式编程####
在Java的演变过程中,Lambda表达式和函数式编程的引入无疑是一次重大的飞跃。本文将深入探讨Lambda表达式的定义、用法及优势,并结合实例说明如何在Java中利用Lambda表达式进行函数式编程。通过对比传统编程方式,揭示Lambda表达式如何简化代码、提高开发效率和可维护性。 ####
下一篇
无影云桌面