异常、断言、日志
处理错误
写程序时当然会遇到很多错误,可能是数组溢出,指针等等。Java对于这些错误,采取了一种异常处理机制:对于一个错误的方法,并不会返回任何值,而是抛出(throw)一个封装了错误信息的对象。
异常分类
所有异常都是由Throwable
继承而来:Error
类主要描述了Java运行时系统的内部错误和资源耗尽错误;RuntimeException
主要是由编程错误导致的异常,另一个是其他异常。
RuntimeException
异常主要有: 不是派生于RuntimeException
的异常包括:
- 错误的强制类型转换 试图超越文件末尾继续读取数据
- 数组访问越界 试图打开一个不存在的文件
- 访问
null
指针 试图根据给定的字符串查找Class
对象
Error
类异常和RuntimeException
类异常称为非检查型异常,其他的异常称为检查型异常
声明检查型异常
以下四种情况用throws
子句声明异常:
- 调用了一个抛出检查型异常的方法
- 检测到了一个错误,并且利用
throw
语句抛出一个检查型异常 - 程序出现了一个错误
- Java虚拟机或运行时库出现内部错误
对于一个方法抛出的检查型异常都应该通过方法首部的异常规范来声明异常:(非检查型异常不建议声明)
public Image loadImage(String s) throws FileNotFoundException, EOFException {
}
如何抛出异常
使用throw
语句抛出异常
先找到一个合适的异常类,声明一个要抛出的异常
String readDate(Scanner in) throws EOException {
...
throw new EOException();
}
自定义异常类
若标准异常类无法解决错误,则需要自定义一个异常类(派生于Exception
的类或者派生Exception
的子类)
class FileFormatException extends IOException {
public FileFormatException() {}
public FileFormatException(String grape) {
super(gripe);
}
}
捕获异常
捕获异常
try {
}
catch(ExceptionType e) {
handler for this type
}
如果try语句块中的任何代码块抛出了catch语句中指定的异常类,那么
- 程序将跳过try语句块的其余代码
- 程序将执行catch子句的处理器代码
如果try语句块没有抛出任何异常,那么程序将跳过catch子句;如果方法中的代码抛出了catch子句中没有声明的异常,那么方法会立即退出。
public void read(String filename) {
try {
var in = new FileInputStream(filename);
int b;
while ((b = in.read()) != 1) {
process input;
}
}
catch(IOException exception) {
exception.printStackTrace();
}
}
捕获多个异常
try {
}
catch() {
}
catch() {
}
再次抛出异常与异常链
finally子句
无论前面catch
是否捕获异常,try
语句是否抛出异常,finally
子句是一定会执行的部分
- 不要在
finally
子句中使用return
语句
try-with-Resources语句
分析堆栈轨迹元素
使用异常的技巧!!!
-
异常处理并不能替代一些简单的测试(使用类的方法)
-
不要过分地细化异常
即一个try语句块,多个catch语句块而不是多个try-catch
-
充分利用异常层次结构
不要只抛出
RuntimeException
异常。应该寻找一个合适的子类或自定义异常。不要只捕获
Throwable
异常 -
不要压制异常
-
准确抛出异常
-
尽量传递异常
使用断言
断言的概念
assert
关键字
assert
condition;
assert
condition: expression; // expression是为了产生一个消息字符串
如果条件为false
,则抛出一个AssertionError
异常
作用:加入检查,但产生代码时会自动删除检查
启用和禁用断言
在默认情况下,断言是禁用的。(但是IDEA好像不一样)
日志(不是Java SE主线内容,呜呜呜)
该API主要是为了解决频繁使用System.out.println()
方法设计的
ssertionError`异常
作用:加入检查,但产生代码时会自动删除检查
启用和禁用断言
在默认情况下,断言是禁用的。(但是IDEA好像不一样)
日志(不是Java SE主线内容,呜呜呜)
该API主要是为了解决频繁使用System.out.println()
方法设计的