一、什么是异常
1.异常的概念
所谓异常就是没有达到程序预期的结果。
2.异常与错误
- 错误:虚拟机等相关的错误,开发人员无法在程序中做预处理
- 异常:开发人员可以根据不同的异常类型设定一些处理方案
3.java中的异常体系
- Error : 错误类
- Exception : 异常类(开发中重点关注的地方)
二、Java异常处理机制
1.异常捕获及处理
- try : 表示可能出现问题的代码块,也是被捕获的代码段(不可能出现异常的代码块不建议放于其中)
- catch : 当遇到对应的异常时,进行处理的代码块(可以针对不同的异常进行不同的处理或相同的处理)
- finally : 无论是否出现异常,最终都会执行的代码块,一般用于释放资源,关闭连接、最终清理工作等
(1)不同类型的异常进行相应的捕获处理
try {
//可能出现错误的代码块
} catch (ArrayIndexOutOfBoundsException ex) {
//出现ArrayIndexOutOfBoundsException异常时的处理
} catch (Exception ex) {
//其他非ArrayIndexOutOfBoundsException异常时的处理
} finally {
//无论是否出现异常,最终都会执行的代码块
}
(2)多个异常使用相同的处理:多个异常类型使用 | 隔开
try {
//可能出现问题的代码块
} catch (ArrayIndexOutOfBoundsException | IOException e) {
//同时捕获多个类型的异常,进行相同的处理
}
(3)捕获异常时同时需要记录异常
- 日志方式:在测试或开发环境追踪问题的根据
- 控制台输出:一般在开发环境中使用
注:在记录的时候,最好有详细的上下文说明,并使用异常对象的printStackTrace()方法记录异常的调用栈链
2.断言
断言只是一种检测是否达到预期结果的判断的方式,并不参与异常处理,一般用于参数判断和单元测试等(断言默认是不开启的,可以通过修改JVM参数来开启:-ea或-enableassertions)
- assert boolean表达式
- assert boolean表达式 : 错误提示
注:使用assert关键词的结果:
- 表达式为true:即通过,不做任何处理
- 表达式为false:即未通过,会抛出一个AssertionError
/**
* 使用默认的会抛出AssertionError
*/
public static void defaultDemo() {
try {
int a = 10;
assert (a == 11);
} catch (Throwable e) {
e.printStackTrace();
}
}
/**
* 使用默认的会抛出AssertionError,并返回我们设置的错误提示信息
*/
public static void useMessage() {
try {
int a = 10;
assert (a == 11) : "不出false";
} catch (Throwable e) {
e.printStackTrace();
}
}
三、自定义异常
- 1.自定义异常一般继承自Exception或RuntimeException
- 可查的异常一般继承自Exception
- 不可查的异常一般继承自RuntimeException
- 2.建议有以下构造方法
- (1)无参的构造方法
- (2)接收一个异常提示参数的构造方法
- (3)接收一个Exception或Exception子类对象的构造方法
- (4)接收一个异常提示参数和一个Exception对象参数的构造方法
/**
* 自定义异常
* @author shixinke
* @date 2019-01-14
*/
public class MyException extends Exception {
/**
* 自定义一个属性code
*/
private int code;
/**
* 1.建议有一个无参的构造方法
*/
public MyException() {
super();
}
/**
* 2.建议有一个只有一个message的构造方法
* @param message
*/
public MyException(String message) {
super(message);
}
/**
* 3.建议有一个可以接收Throwable类或自子类对象的构造方法
* @param cause
*/
public MyException(Throwable cause) {
super(cause);
}
/**
* 4.建议有一个可以接受自定义message和继承自Throwable类或其子类对象的参数的构造方法
* @param message
* @param cause
*/
public MyException(String message, Throwable cause) {
super(message, cause);
}
/**
* 自定义一个构造函数
* @param code
* @param message
*/
public MyException(int code, String message) {
this(message);
this.code = code;
}
/**
* 获取异常码
* @return
*/
public int getCode() {
return this.code;
}
}
class ExceptionDemo {
public int divide(int a, int b) throws MyException {
if ( b == 0) {
throw new MyException(100, "被除数不能为0");
}
return a / b;
}
}
public class MyExceptionDemo {
public static void main(String[] args) {
ExceptionDemo demo = new ExceptionDemo();
try {
demo.divide(100, 0);
} catch (MyException e) {
System.out.println(e.getMessage() );
e.printStackTrace();
}
System.out.println("demo结束");
}
}