如何优雅的实现异常块

简介: 在项目中,我们会遇到异常处理,对于运行时异常,需要我们自己判断处理。对于受检异常,需要我们主动处理。但是繁琐的try{}caht嵌套在代码里,看着很不舒服,这里我们不讨论性能,就代码来讲,来看看如何将他隐藏起来。原理是不变的。变得是写法。下面我们来看如何优雅的处理异常块。
在项目中,我们会遇到异常处理,对于运行时异常,需要我们自己判断处理。对于受检异常,需要我们主动处理。
但是繁琐的try{}caht嵌套在代码里,看着很不舒服,这里我们不讨论性能,就代码来讲,来看看如何将他隐藏起来。原理是不变的。变得是写法。下面我们来看如何优雅的处理异常块。

在这之前。你需要知道以下几个概念:
行为参数化:
是java8提出的,函数式编程的一种思想,通过把代码包装为参数传递行为,即把代码逻辑包装为一个参数,传到方法里。

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

函数式接口:
本质上是只有一个抽象方法的普通接口,可以被隐式的转换为Lambda表达式,需要用注解定义(@FunctionalInterface)。默认方法和静态方法可以不属于抽象方法,可以在函数式接口中定义。

@FunctionalInterfacepublic
interface ObjectMethodFunctionalInterface {
void count(int i);
String toString(); //same to Object.toString
int hashCode(); //same to Object.hashCode
boolean equals(Object obj); //same to Object.equals
}

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

    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
 */
@FunctionalInterface
public 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】
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
 */
@FunctionalInterface
public 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 -> String的Lambda表达式都可以作为参数传入。只要符合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);
    }
相关文章
|
12月前
|
Web App开发 前端开发 JavaScript
揭秘!前端大牛们如何巧妙利用CSS3,打造炫酷视觉效果!
【10月更文挑战第31天】前端开发面临复杂布局的挑战,本文介绍了几种提升开发效率和代码质量的工具和技术。基础的HTML和CSS可以应对大部分布局需求,而Firefox开发者工具、VS Code、Vue、React等则能应对更复杂的布局,帮助开发者构建高性能、用户友好的网页应用。
271 4
|
数据中心
蓝易云 - 1U和2U的服务器怎么选择
总的来说,选择1U还是2U服务器,主要取决于你的特定需求,包括空间、性能、扩展性和散热等因素。
991 6
|
存储 算法
《LeetCode 热题 HOT 100》——寻找两个正序数组的中位数
《LeetCode 热题 HOT 100》——寻找两个正序数组的中位数
175 0
|
存储 监控 Serverless
函数计算产品使用问题之怎么批量下载Stable Diffusion(SD)图片
实时计算Flink版作为一种强大的流处理和批处理统一的计算框架,广泛应用于各种需要实时数据处理和分析的场景。实时计算Flink版通常结合SQL接口、DataStream API、以及与上下游数据源和存储系统的丰富连接器,提供了一套全面的解决方案,以应对各种实时计算需求。其低延迟、高吞吐、容错性强的特点,使其成为众多企业和组织实时数据处理首选的技术平台。以下是实时计算Flink版的一些典型使用合集。
153 0
函数计算产品使用问题之怎么批量下载Stable Diffusion(SD)图片
|
存储 Python
理解Python中的变量和数据类型
【4月更文挑战第8天】本文介绍了Python中的变量和数据类型。变量是内存中的存储单元,用于保存数据,无需预先声明类型,可通过赋值创建。Python的基本数据类型包括数值(整型、浮点型、复数)、布尔型、字符串、列表、元组、范围、集合和字典。Python支持变量类型动态变化,允许同一变量赋予不同类型的值。此外,还提供了数据类型转换函数如`int()`, `float()`, `str()`和`bool()`。理解这些概念对编写高效Python代码至关重要。
225 1
|
存储 关系型数据库 MySQL
实时计算 Flink版产品使用合集之如何配置可以实现实时同步多张MySQL源表时只读取一次binlog
实时计算Flink版作为一种强大的流处理和批处理统一的计算框架,广泛应用于各种需要实时数据处理和分析的场景。实时计算Flink版通常结合SQL接口、DataStreamAPI、以及与上下游数据源和存储系统的丰富连接器,提供了一套全面的解决方案,以应对各种实时计算需求。其低延迟、高吞吐、容错性强的特点,使其成为众多企业和组织实时数据处理首选的技术平台。以下是实时计算Flink版的一些典型使用合集。
|
人工智能 安全 算法
如何在激烈的市场竞争中实现互联网产品的用户增长和维护?
如何在激烈的市场竞争中实现互联网产品的用户增长和维护?
326 0
|
前端开发 Java 数据库
LayUI之动态树
LayUI之动态树
105 0
|
存储 缓存 NoSQL
LSM-Tree - LevelDb了解和实现
LSM-Tree - LevelDb了解和实现
395 0
下一篇
开通oss服务