精华内容
下载资源
问答
  • 抛出受检异常的时候,我们的接口应该带上throw关键字,但通过lambda表达式实现的Consumer的accept方法并不带有关键字,因此在lambda表达式中不能抛出受检异常必须把它吃掉 转载于:...

    抛出受检异常的时候,我们的接口应该带上throw关键字,但通过lambda表达式实现的Consumer的accept方法并不带有关键字,因此在lambda表达式中不能抛出受检异常必须把它吃掉

     

      

     

    转载于:https://www.cnblogs.com/lccsblog/p/11341200.html

    展开全文
  • //编译通过 Stream.of("a", "b", "c").forEach(str -> { throw new RuntimeException(new IOException()); }); 转换成RuntimeException即可

    //编译通过
    Stream.of("a", "b", "c").forEach(str -> {
        throw new RuntimeException(new IOException());
    });

    转换成RuntimeException即可

    展开全文
  • Lambda表达式与受检异常的矛盾 Lambda极大简化了我们的代码,让我们的代码变得整洁优雅(虽然有很多表达式很难看懂,没怎么特意学习lambda表达式的话)。但是当Lambda表达式中需要处理受检异常时,就会破坏掉这种整洁...

    Lambda表达式与受检异常的矛盾

    Lambda极大简化了我们的代码,让我们的代码变得整洁优雅(虽然有很多表达式很难看懂,没怎么特意学习lambda表达式的话)。但是当Lambda表达式中需要处理受检异常时,就会破坏掉这种整洁优雅的布局,让代码变得非常难看。

     这里借鉴这里大佬的例子做一个举例说明

    long count = Files.walk(Paths.get("D:/Test"))                      // 获得项目目录下的所有文件
                    .filter(file -> !Files.isDirectory(file))          // 筛选出文件
                    .filter(file -> file.toString().endsWith(".java")) // 筛选出 java 文件
                    .flatMap(file -> {
                        try {
                            return Files.lines(file);
                        } catch (IOException ex) {
                            ex.printStackTrace(System.err);
                            return Stream.empty();                     // 抛出异常时返回一个空的 Stream
                        }
                    })                                                 // 按行获得文件中的文本
                    .filter(line -> !line.trim().isEmpty())            // 过滤掉空行
                    .count();

    作为一名资深强迫者,怎么会让这种情况出现呢╮(╯▽╰)╭。既然,他俩出现矛盾了,不想在一起干活了肯定就要出来一个和事佬过来劝架啦!

    劝架流程(受检异常转移)

     既然我Lambda不想和异常合作,但是工作老板下命令了。必须你俩都有都得干(没办法,底层没抛出异常,必须捕获)。那就只能辛苦和事佬了。Lambda和和事佬合作,和事佬和受检异常合作。

     首先定义一个和事佬,处理异常。Lambda调用和事佬

    /**
     * 受检的 function
     * @FunctionalInterface 用于编译级错误检查,声明该接口是函数式接口。该注解修饰的接口只能有一个抽 
     * 象方法
     */
    @FunctionalInterface
    public interface CheckedFunction<T, R> {
    
    	/**
    	 * Run the Function
    	 *
    	 * @param t T
    	 * @return R R
    	 * @throws Throwable CheckedException
    	 */
    	@Nullable
    	R apply(@Nullable T t) throws Throwable;
    
    }
    @UtilityClass
    public class Unchecked {
        //这里其实是将Function的方法实现了一下返回。异常在内部已经被捕获不会到Lambda层面
        public static <T, R> Function<T, R> function(CheckedFunction<T, R> mapper) {
    		Objects.requireNonNull(mapper);
    		return t -> {
    			try {
    				return mapper.apply(t);
    			} catch (Throwable e) {
    				throw Exceptions.unchecked(e);
    			}
    		};
    	}
    }

     到时候让lambda和和事佬Unchecked沟通,和事佬再和真正的要求检查异常的沟通,异常和事佬捕获。并对其作出处理。

    Unchecked.function(uncheckedFunction)即可

    参考这里

     

    展开全文
  • Java8:当 Lambda 遇上受检异常 前言 我今天高高兴兴,想写个简单的统计一个项目下有多少行代码的小程序,于是咔咔的写下: long count = Files.walk(Paths.get("D:/Test")) // 获得项目目录下的所有目录及文件 ....

    Java8:当 Lambda 遇上受检异常

    前言

    我今天高高兴兴,想写个简单的统计一个项目下有多少行代码的小程序,于是咔咔的写下:

    long count = Files.walk(Paths.get("D:/Test"))                      // 获得项目目录下的所有目录及文件
                    .filter(file -> !Files.isDirectory(file))          // 筛选出文件
                    .filter(file -> file.toString().endsWith(".java")) // 筛选出 java 文件
                    .flatMap(file -> Files.lines(file))                // 按行获得文件中的文本
                    .filter(line -> !line.trim().isEmpty())            // 过滤掉空行
                    .count();
    
    System.out.println("代码行数:" + count);
    

    题外话: Files.walk(Path) 在 JDK1.8 时添加,深度优先遍历一个 Path (目录),返回这个目录下所有的Path(目录和文件),通过 Stream 返回; Files.lines(Path) 也是在 JDK1.8 时添加,功能是返回指定Path(文件)中所有的行,通过 Stream 返回

    然后,编译不过 —— 因为 Files.lines(Path) 会抛出 IOException,如果要编译通过,得这样写:

    long count = Files.walk(Paths.get("D:/Test"))                      // 获得项目目录下的所有文件
                    .filter(file -> !Files.isDirectory(file))          // 筛选出文件
                    .filter(file -> file.toString().endsWith(".java")) // 筛选出 java 文件
                    .flatMap(file -> {
                        try {
                            return Files.lines(file);
                        } catch (IOException ex) {
                            ex.printStackTrace(System.err);
                            return Stream.empty();                     // 抛出异常时返回一个空的 Stream
                        }
                    })                                                 // 按行获得文件中的文本
                    .filter(line -> !line.trim().isEmpty())            // 过滤掉空行
                    .count();
    
    System.out.println("代码行数:" + count);
    

    我的天,这个时候我强迫症就犯了——因为这样的 Lambda 不是 one-liner expression,不够简洁,也不直观。如果 Stream的流式操作中多几个需要抛出受检异常的情况,那代码真是太难看了,所以为了 one-liner expression 的 Lambda,我们需要解决的办法。

    解决方案

    解决方法一

    通过新建一个方法( ? 无奈但是纯洁的微笑)

    public static void main(String[] args) throws Exception {
        long count = Files.walk(Paths.get("D:/Test"))                       // 获得项目目录下的所有文件
                        .filter(file -> !Files.isDirectory(file))           // 筛选出文件
                        .filter(file -> file.toString().endsWith(".java"))  // 筛选出 java 文件
                        .flatMap(file -> getLines(file))                    // 按行获得文件中的文本
                        .filter(line -> !line.trim().isEmpty())             // 过滤掉空行
                        .count();
    
        System.out.println("代码行数:" + count);
    }
    
    private static Stream<String> getLines(Path file) {
        try {
            return Files.lines(file);
        } catch (IOException ex) {
            ex.printStackTrace(System.err);
            return Stream.empty();
        }
    }
    

    这种解决方法下,我们需要处理受检异常 —— 即在程序抛出异常的时候,我们需要告诉程序怎么去做(getLines 方法中抛出异常时我们输出了异常,并返回一个空的 Stream)

    解决方法二

    将会抛出异常的函数进行包装,使其不抛出受检异常

    如果一个 FunctionInterface 的方法会抛出受检异常(比如 Exception),那么该 FunctionInterface 便可以作为会抛出受检异常的 Lambda 的目标类型。

    我们定义如下一个受检的 FunctionInterface:

    @FunctionalInterface
    interface CheckedFunction<T, R> {
        R apply(T t) throws Throwable;
    }
    

    那么该 FunctionalInterface 便可以作为类似于file -> File.lines(file) 这类会抛出受检异常的 Lambda 的目标类型,此时 Lambda 中并不需要捕获异常(因为目标类型的 apply 方法已经将异常抛出了)—— 之所以原来的 Lambda 需要捕获异常,就是因为在流式操作 flatMap 中使用的 java.util.function 包下的 Function<T, R> 没有抛出异常:

    java.util.function.Function
    

    那我们如何使用 CheckedFunction 到流式操作的 Lambda 中呢? 首先我们定义一个 Attempt 接口,它的 apply 静态方法提供将 CheckedFunction 包装为 Function 的功能:

    public interface Attempt {
    
       static <T, R> Function<T, R> apply(CheckedFunction<T, R> function) {
            Objects.requireNonNull(function);
            
            return t -> {
                try {
                    return function.apply(t);
                } catch (Exception ex) {
                    throw new RuntimeException(ex);
                }
            };
        }
    
    }
    

    然后在原先的代码中,我们使用 Attempt.apply 方法来对会抛出受检异常的 Lambda 进行包装:

    long count = Files.walk(Paths.get("D:/Test"))              // 获得项目目录下的所有文件
                    .filter(file -> !Files.isDirectory(file))          // 筛选出文件
                    .filter(file -> file.toString().endsWith(".java")) // 筛选出 java 文件
            
                    .flatMap(Attempt.apply(file -> Files.lines(file)))        // 将 会抛出受检异常的 Lambda 包装为 抛出非受检异常的 Lambda
            
                    .filter(line -> !line.trim().isEmpty())            // 过滤掉空行
                    .count();
    
    System.out.println("代码行数:" + count);
    

    此时,我们便可以选择是否去捕获异常(RuntimeException)。这种解决方法下,我们一般不关心抛出异常的情况 —— 比如自己写的小例子,抛出了异常程序就该终止;或者你知道这个 Lambda 确实 100% 不会抛出异常。

    不过我更倾向于抛出异常时,我们来指定处理的方式:

    static <T, R> Function<T, R> apply(CheckedFunction<T, R> function, Function<Throwable, R> handler) {
        Objects.requireNonNull(function);
        Objects.requireNonNull(handler);
    
        return t -> {
            try {
                return function.apply(t);
            } catch (Throwable e) {
                return handler.apply(e);
            }
        };
    }
    

    比如我们前面的例子,如果 file -> Files.lines(file) 抛出异常了,说明在访问 file 类的时候出了问题,我们可以就假设这个文件的行数为 0 ,那么默认值就是个空的 Stream(当然你也可以选择顺手记录一下异常):

    long count = Files.walk(Paths.get("D:/Test"))              // 获得项目目录下的所有文件
                    .filter(file -> !Files.isDirectory(file))          // 筛选出文件
                    .filter(file -> file.toString().endsWith(".java")) // 筛选出 java 文件
            
                    .flatMap(TryTo.apply(file -> Files.lines(file), ex -> Stream.empty()))
            
                    .filter(line -> !line.trim().isEmpty())            // 过滤掉空行
                    .count();
    
    System.out.println("代码行数:" + count);
    

    使用 CheckedFunction这种方式更为通用 —— 类似的,我们可以包装 CheckedConsumer 为 java.util.function.Consumer,包装 CheckedSupplier 为 java.util.function.Suppiler,CheckedBiFunction 为 java.util.function.BiFunction 等:

    public interface Attempt {
    
        ......
            
        /**
         * 包装受检的 Consumer
         */
        static <T> Consumer<T> accept(CheckedConsumer<T> consumer) {
            Objects.requireNonNull(consumer);
    
            return t -> {
                try {
                    consumer.accept(t);
                } catch (Throwable e) {
                    throw new RuntimeException(e);
                }
            };
        }
    
        /**
         * 包装受检的 Consumer,并自定义异常处理
         */
        static <T> Consumer<T> accept(CheckedConsumer<T> consumer, Consumer<Throwable> handler) {
            Objects.requireNonNull(consumer);
            Objects.requireNonNull(handler);
    
            return t -> {
                try {
                    consumer.accept(t);
                } catch (Throwable e) {
                    handler.accept(e);
                }
            };
        }
    }
    

    就我个人观点而言,我真的不喜欢 Java 中的受检(Checked)异常,我认为所有的异常都应该是非受检(Unchecked)的 —— 因为一段代码如果会产生异常,我们自然会去解决这个问题直到其不抛出异常或者捕获这个异常并做对应处理 —— 强制性的要求编码人员捕获异常,带来的更多的是编码上的不方便和代码可读性的降低(因为冗余)。不过既然受检异常已经是 Java 中的客观存在的事物,所谓“道高一尺,魔高一丈” —— 总是会有办法来应对。

    (想自学习编程的小伙伴请搜索圈T社区,更多行业相关资讯更有行业相关免费视频教程。完全免费哦!)

    展开全文
  • .flatMap(Try.of(file -> Files.lines(file))) // 将 会抛出受检异常Lambda 包装为 抛出非受检异常的 Lambda .filter(line -> !line.trim().isEmpty()) // 过滤掉空行 .count(); System.out.println("代码...
  • jdk8 lambda表达式抛出异常

    千次阅读 2019-01-10 16:53:00
    * 把受检异常包装成非受检异常抛出,避免破坏Java异常的结构,通过泛型的方式解决这个问题 * @param e * @param * @throws E */ static <E extends Exception> void lambdaThrowException(Exception e) ...
  • lambda表达式内出现异常无法throw抛出

    千次阅读 2021-02-24 15:56:44
    今儿在使用lambda表达式时,lambda表达式内出现了异常,准备直接抛出,没想到却还是报错: 由于博主lambda表达式用的比较少,刚看到这问题时,可以说是一脸懵逼.毕竟两边的提示可以说是前后矛盾啊. 刷新几下编译器还是...
  • 如何优雅的处理Lambda异常?

    千次阅读 2019-10-28 22:04:21
    1.如何优雅的处理Lambda异常? java8新增的特性Lambda表达式为我们使用匿名内部类提供了非常简洁的方式。然而,平时在使用lambda的过程发,却发现lambda表达式中如果存在异常,使用try-catch去处理异常,那么这个...
  • Lambda

    千次阅读 2019-10-21 12:46:57
    文章目录一. 简介二. 使用效果2.1 未使用 lambda 和 使用 lambda 的区别三....可以写更简洁、更 灵活的代码。作为一种更紧凑的代码风格,使 Java的语言表达能力得到了提升. 二. 使用效果 2.1 未使用 lambda ...
  • Lambda表达式

    2019-11-05 20:24:14
    实现了匿名接口的匿名方法的表达式,它有参数列表、函数主体、返回类型,也可能抛出异常Lambda的组成 Lambda表达式有三个部分 参数列表 箭头 -> 把参数列表与Lambda主体分隔开 Lambda主体,表达式就是...
  • Lambda简介

    2021-05-15 11:23:47
    Lambda本质上是一个函数,不属于特定的类,具备参数列表、函数主体、返回类型,可以抛出异常 Lambda没有具体的函数名称(匿名函数) Lambda允许将函数作为一个方法的参数(函数作为方法参数) Lambda表达式可以让...
  • java的lambda表达式

    2020-01-20 17:10:36
    lambda表达式的格式 以->分隔,前边是参数列表,后边是表达式体也就是具体要执行得到逻辑。 根据参数列表的个数有无返回值等可以分为6种形式,这个不必多说。...需要注意的是,若 Lambda 表达式抛出一个受检异常...
  • 关于Lambda表达式

    2019-09-18 20:59:08
    可以把Lambda表达式理解为简洁地表示可传递的匿名函数的一种方式:它没有名称,但它有参数列表、函数主体、返回类型,可能还有一个可以抛出异常列表。 匿名——我们说匿名,是因为它不像普通的方法那样有一个...
  • 可以把Lambda表达式理解为简洁地表示可传递的匿名函数的一种方式:它没有名称,但它有参数列表、函数主体、返回类型,可能还有一个可以抛出异常列表。 匿名——它不像普通的方法那样有一个明确的名称 函数...
  • Java8Lambda表达式

    2018-10-25 16:30:30
    Lambda是一个匿名函数,Lambda 允许把函数作为一个方法的参数(函数作为...假如现在有一个需求,为农民写个软件,需求是可以在苹果中挑选所有的红苹果。 第一步,创建Apple类,具有两个属性:颜色和重量,还要...
  • Lambda表达式 详解

    万次阅读 多人点赞 2017-09-28 13:03:30
    可以写更简洁、更灵活的代码。作为一种更紧凑的代码风格,使Java的语言表达能力得到了提升 Lambda 表达式的基础语法 : Java8 中引入了一个新的操作符 "->" 该操作符称为箭头操作符或 Lambda 操作符,箭头操作...
  • 深入理解Java 8 Lambda

    千次阅读 2018-09-11 14:11:43
    深入理解 Java 8 Lambda(语言篇——lambda,方法引用,目标类型和默认方法) 深入理解 Java 8 Lambda(类库篇——Streams API,Collector 和并行) 深入理解 Java 8 Lambda(原理篇——Java 编译器如何处理 ...
  • Lambda 表达式Demoo

    2019-02-02 23:10:06
    可以写更简洁、更 灵活的代码。作为一种更紧凑的代码风格,使 Java的语言表达能力得到了提升。 Lambda表达式和函数式编程有千丝万缕的关系 readme 1)接口内有且仅有一个方法,不能有多个,见下面的函数式接口 ...
  • 目录 ...5、利用 Lambda 表达式抛出异常的方法 6、编译器对 Lambda 做类型检查、类型推断 7、和 void 兼容的 Lambda 8、Lambda 内部引用局部变量 9、方法引用 10、构造函数引用 11、复合...
  • lambda表达式

    2019-02-13 15:59:05
    前段时间一直在看lambda表达式,但是总感觉吃不透,在深入了解lambda表达式的时候,需要很多基础的知识栈。这里就偷一个懒,转载一下个人认为网上关于lambda表达式总结的最好的一篇文章。 注:原译文见 ...
  • 抛出一个受检异常(即:非运行时异常),那么该异常需要在目标接口的抽 象方法上进行声明)。 我们可以在一个接口上使用 @FunctionalInterface 注解,这样做可以检 查它是否是一个函数式接口。同时 javadoc 也会包...
  •   先暂时将Java8中的Lambda表达式看成匿名的函数,它跟一般的方法类似,一样具有参数类型、函数主体、返回值甚至可抛出异常列表。但是,它与一般方法最大的不同是:它可以作为参数传递给方法或者存储在变量中。可...
  • java8 - Lambda表达式

    2020-04-12 17:45:23
    它没有名称,但它有参数列表、函数主体、返回类型,可能还有一个可以抛出异常列表。比如,你现在可以写(int x) -> x + 1,表示“调用时给定参数x,就返回x + 1值的函数”。 lambda组成部分: lambda参数、->...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,276
精华内容 510
热门标签
关键字:

lambda抛出受检异常