写点什么

try{}catch 居然可以隐藏?让我们用函数式接口来实现吧

作者:山河已无恙
  • 2022 年 2 月 09 日
  • 本文字数:3389 字

    阅读完需:约 11 分钟

try{}catch居然可以隐藏?让我们用函数式接口来实现吧

写在前面

  • 很早写的一篇文章,这里分享给小伙伴。

  • 在项目中,我们会遇到异常处理,对于运行时异常,需要我们自己判断处理。对于受检异常,需要我们主动处理

  • 主动处理中繁琐的try{}caht嵌套在代码里,看着很不舒服

  • 这里我们不讨论性能,就代码来讲,来看看如何将他隐藏起来。原理是不变的。变得是写法。下面我们来看如何优雅的处理异常块。

傍晚时分,你坐在屋檐下,看着天慢慢地黑下去,心里寂寞而凄凉,感到自己的生命被剥夺了。当时我是个年轻人,但我害怕这样生活下去,衰老下去。在我看来,这是比死亡更可怕的事。--------王小波

在这之前,你需要知道以下几个概念:

行为参数化:

java8提出的,函数式编程的一种思想,通过把代码包装为参数传递行为,即把代码逻辑包装为一个参数,传到方法里。

Lambda 表达式

java8提出:Lambda表达式理解为简洁的表示可传递的匿名函数的一种方式,它没有名称,但它有函数体参数列表,返回类型。可以抛出一个异常类型。包装代码逻辑为参数即使用Lambda表达式

函数式接口:

本质上是只有一个抽象方法普通接口,可以被隐式的转换为Lambda表达式,需要用注解定义(@FunctionalInterface)。

这里需要注意一点默认方法静态方法虽然不属于抽象方法,但是可以在函数式接口中定义。

@FunctionalInterfacepublicinterface ObjectMethodFunctionalInterface {void count(int i);String toString(); //same to Object.toStringint hashCode(); //same to Object.hashCodeboolean equals(Object obj); //same to Object.equals}
复制代码

如果函数式接口中额外定义多个抽象方法,那么这些抽象方法签名必须和 Object 的 public 方法一样,接口最终有确定的类实现, 而类的最终父类是 Object。 因此函数式接口可以定义 Object 的 public 方法。

行为参数化是指导思想Lambda表达式是表达方式函数式接口是实现手法

如何隐藏

 Class<?> clazz = Class.forName("类名");
复制代码

这句代码想来小伙伴都不陌生。这是一个受检异常,需要抛出一个ClassNotFoundException

正常的写法:

try {            Class<?> clazzOld = Class.forName("类名");        } catch (ClassNotFoundException e) {            e.printStackTrace();        }
复制代码

隐藏之后的写法:

Class<?> clazzNew =classFind( o -> Class.forName(o),"类名");
复制代码


在这里插入图片描述

嗯,我们来看具体的实现:很简单,我们要做的,即把Class<?> clazz = Class.forName("类名");当做一种行为去处理,接受一个 String ,得到一个 Class,所以我们要定义一个函数接口,描述这种行为,这种行为本身是需要处理受检异常的。

/** * @Auther: Liruilong * @Date: 2020/7/29 15:50 * @Description: 由函数名获取元类Class实例 * 函数签名:   String ==> Class */@FunctionalInterfacepublic interface ClassFindInterface {    Class<?> classNametoClass(String className)throws ClassNotFoundException;}
复制代码

这里,因为我们的行为需要抛出异常。所以在接口里也抛出异常。

然后,我们需要定义一个方法,将我们的行为作为参数传进去,同时,捕获一下我们的异常。

public Class classFind(ClassFindInterface classFindInterface,String className){        Class<?> clazz =null;        try {            clazz = classFindInterface.classNametoClass(className);        } catch (ClassNotFoundException e) {            logger4j.error("˙·...·˙`˙·....·…┉═∞═…┉ ═∞═┈━═┈━═┈━═┈━═┈━═☆☆☆☆、"+e.getMessage()+"☆☆☆☆☆☆☆☆☆");            e.printStackTrace();        }        return clazz;    }
复制代码

然后,我们可以调用我们的方法classFind方法,

Class<?> clazzNew =classFind( o -> Class.forName(o),"类名");
复制代码

当然。其实这种思想并不简单的可以做捕获异常的处理,

我们来看一个 Demo

文本文件转换为字符串:

在我看来;将文本文件转换为字符串,我们需要使用高级流包装低级流,然后做缓存读出来。这里,我们不可避免的会遇到异常处理,流的关闭等操作,下面我们将这些代码都异常起来。专心写读的逻辑即可。

我的思路:我对 java IO 用的不是很熟,大家有好的方法请留言,相互学习:

FileInputStream fileInputStream = new FileInputStream(file))InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream))BufferedReader bufferedReader = new BufferedReader(inputStreamReader))String str = bufferedReader.readLine()
复制代码

字节流-》字符流-》字符缓存流 即 将字节流转换为字符流之后在用高级流包装。

所以我的思路是避免在逻辑里出现太多的IO流关闭,和异常捕获,专心处理读取逻辑即可,结合以下两种技术:

  • try(){}【自动关闭流,1.7支持】

  • lambda特性来实现【行为参数化,1.8】

描述一个行为,BufferReader -> String

package com.liruilong.demotext.service.utils.interfaceutils; import java.io.BufferedReader;import java.io.IOException; /** * @Description : 函数接口,描述BufferedReader ->String的转化方式 * @Author: Liruilong * @Date: 2020/3/17 15:44 */@FunctionalInterfacepublic interface InputStreamPeocess {    /**     * @Author Liruilong     * @Description 方法签名 BufferedReader ->String     * @Date 15:47 2020/3/17     * @Param [inputStream]     * @return com.liruilong.demotext.service.utils.InputStream     **/     String peocess(BufferedReader bufferedReader) throws IOException;}
复制代码

执一个行为,嵌入到定式里,任何BufferReader -> StringLambda表达式都可以作为参数传入。只要符合peocess方法的签名即可。

 /**     * @return java.lang.String     * @Author Liruilong     * @Description 环绕处理     * @Date 17:14 2020/3/17     * @Param [inputStreamPeocess, file]     **/     public static String fileToBufferedReader(InputStreamPeocess inputStreamPeocess, File file) {         string  resoult= null;        try (FileInputStream fileInputStream = new FileInputStream(file)) {            try (InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream)) {                try (BufferedReader bufferedReader = new BufferedReader(inputStreamReader)) {                    resoult = inputStreamPeocess.peocess(bufferedReader);                }            }        } catch (IOException e) {            e.printStackTrace();        } finally {            return resoult ;        }    }
复制代码

如何使用这个定义好的行为

/**     * @return java.lang.String     * @Author Liruilong     * @Description 文件转字符串     * @Date 17:22 2020/3/17     * @Param [file]     **/     public static String readJsonToString(File file) {        return  fileToBufferedReader((bufferedReader) -> {            String str = null;            StringBuilder stringBuilder = new StringBuilder();            while ((str = bufferedReader.readLine()) != null) {                stringBuilder.append(str);            }            return stringBuilder.toString();        }, file);    }
复制代码

关于 Java 中 try{}catch 的隐藏就和小伙伴分享到这里

发布于: 2022 年 02 月 09 日阅读数: 71
用户头像

CSDN博客专家,华为云云享专家,RHCE/CKA认证 2022.01.04 加入

Java 后端一枚,技术不高,前端、Shell、Python 也可以写一点.纯种屌丝,不热爱生活,热爱学习,热爱工作,喜欢一直忙,不闲着。喜欢篆刻,喜欢吃好吃的,喜欢吃饱了晒太阳。

评论

发布
暂无评论
try{}catch居然可以隐藏?让我们用函数式接口来实现吧