—引:“ 理想世界里,用户输入数据的格式永远正确,选择打开的文件也一定存在,代码永远不会出现bug。”
Java语言中的三种错误处理机制:
- 抛出
异常
。- 使用
断言
。日志
记录。
一、异常概念
期望: 如果由于出现错误而使某些操作没有完成,程序应该
返回到一种
安全状态
,并能够让用户执行其他的命令。允许用户保存所有工作的结果,并
以妥善的方式终止程序
。
1.1 异常范围:
-
用户输入错误。
-
设备错误。
-
物理限制。
-
代码错误。
1.2 异常分类:
-
在Java程序设计语言中,异常对象都派生于
Throwable类
的一个类实例。 -
Error类
层次结构描述了Java运行时系统的内部错误和资源耗尽错误。 -
Excepiton类
层次结构分解为两个分支:-
程序本身问题:
RuntimeException类
分支。 -
程序本身没有问题:其他异常类分支,如
IOException类
等。
-
-
一个方法必须声明所有可能抛出的检查型异常,而非检查型异常要么在你的控制之外(
Error
),要么是由从一开始就应该避免的情况所导致(RuntimeException
)。
二、异常使用
2.1 异常声明:
/* *
* throws关键字声明哪些异常.
*/
public void readFile (String fileName) throws FileNotFoundException{
// doSomething...
}
2.2 异常类创建及调用:
/* *
* 定义FileNotExistException派生于IOException类。
* 定义无参构造器。
* 定义返回错误信息方法。
*/
public class FileNotExistException extends IOException {
public FileNotExistException() {
}
public FileNotExistException(String message) {
super(message);
}
}
/* *
* 定义一个读取文件方法。
* 使用throws关键字声明自定义的异常类,并抛出异常。
*/
public static void readFile(String fileName) throws FileNotExistException {
if (null == fileName || fileName.trim().length() == 0) {
//异常抛出
throw new FileNotExistException();
}
}
三、异常捕获
如果发生了某个异常,但没有在任何地方捕获这个异常,程序就会终止。
有些代码必须捕获异常。
3.1 捕获结构:
/* *
* 定义一个读取文件方法。
* 使用try/catch/finally关键字 进行异常捕获。
* try语句块:执行一些操作。
* catch:需要捕获的异常类型。
* finally语句块:无论如何都会被执行。
*/
public static void readFile() {
try {
System.out.println("做某些事...");
} catch (Exception e) {
System.out.println("发生异常后,做某些事...");
e.printStackTrace();
} finally {
System.out.println("无论如何都会被执行");
}
}
3.2 一些说明:
执行流程: 如果
try
语句块中的任何代码抛出
了catch
子句指定
的一个异常类。那么:
程序将跳过
try
语句块的其余代码。程序将执行
catch
子句中处理器的代码。关于
finally
:
finally
中的返回值会遮蔽原来的返回值。该语句体中,主要用于资源释放,
不要放入流程控制语句。
使用场景: 尽量
捕获
那些你知道如何处理的异常
,而继续传播
那些你不知道怎样处理的异常
。使用技巧:
异常处理不能代替简单的测试。
不要过分地细化异常。
充分利用异常层次结构。
不要压制异常。
不要羞于传递异常,更高层的方法通常可以更好地通知用户发生了错误。
四、断言
断言(assertion)是一种在程序中的一阶
布尔逻辑
,目的为了表示与验证软件开发者预期的结果。在Java中,条件并不会自动地成为错误报告的一部分。如果希望看到这个条件,就必须将它以字符串的形式传递给
AssertionError
对象。
4.1 使用前提:
-
使用
assert
关键字进行断言。 -
断言失败是致命的,不可恢复的错误。
-
断言检查只是在开发和测试阶段打开,只应该用于在
测试
确定程序内部错误的位置。
4.2 断言使用:
// 若断言num为非负数,则:
assert num >= 0;
// 若需要将值传递给AssertionError对象,则:
assert num >= 0 : num;
五、日志
断言
是一种测试和调试阶段使用的战术性工具,日志
则是一种在程序整个生命周期都可以使用的战略性工具。记录日志的常见用途是记录那些预料之外的异常。
常用的高性能日志框架:Log4j 2-官方文档
5.1 日志API优点:
-
可以很容易地取消全部日志记录。
-
可以很简单地禁止日志记录。
-
可以被定向到不同处理器。
-
记录器和处理器都可以对记录进行过滤。
-
可以采用不同的方式格式化。
-
可以使用多个日志记录器。
-
日志系统的配置由配置文件控制。
5.2 日志技巧:
-
对于一个简单的应用,选择一个日志记录器。
-
默认的日志配置会把级别等于或高于
INFO
的所有消息记录到控制台。
5.3 使用log4j-api
进行日志记录:
public class Sample {
/* *
* 通过当前类的字节码,定义日志记录器。
*/
private static final Logger LOGGER = LogManager.getLogger(Sample.class);
public static void main(String[] args) {
String msg = "some info...";
int num = 1;
// 调用info级别方法。
// 通过占位符{},实现参数化打印。
LOGGER.info("msg:={},num={}", msg, num);
// print 2022-01-31 21:10:24 [main] INFO Sample:28 - msg:=some info...,num=1
}
}
六、结束语
“-------怕什么真理无穷,进一寸有一寸的欢喜。”
微信公众号搜索:饺子泡牛奶。