5

Java中try{}catch的隐藏(如何优雅的实现异常块)

 2 years ago
source link: https://liruilongs.github.io/2020/07/30/Java/Java%E4%B8%ADtry%7B%7Dcatch%E7%9A%84%E9%9A%90%E8%97%8F(%E5%A6%82%E4%BD%95%E4%BC%98%E9%9B%85%E7%9A%84%E5%AE%9E%E7%8E%B0%E5%BC%82%E5%B8%B8%E5%9D%97)/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Java中try{}catch的隐藏(如何优雅的实现异常块)

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

  • 很早写的一篇文章,这里分享给小伙伴。
  • 在项目中,我们会遇到异常处理,对于运行时异常,需要我们自己判断处理。对于受检异常,需要我们主动处理
  • 主动处理中繁琐的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方法。

行为参数化是指导思想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
*/
@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】

描述一个行为,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
*/
@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 -> 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的隐藏就和小伙伴分享到这里


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK