1. Throwable体系:
- Error:严重错误Error,无法通过处理的错误,只能事先避免,好比绝症。
- Exception:表示异常,异常产生后程序员可以通过代码的方式纠正,使程序继续运行,是必须要处理的。好比感冒、阑尾炎。
2. 异常处理
Java异常处理的五个关键字:try、catch、finally、throw、throws
-
throw 用在方法内,用来抛出一个异常对象,将这个异常对象传递到调用者处,并结束当前方法的执行。
对对象为null的值进行了抛出异常操作:throw new 异常类名(参数);
public static <T> T requireNonNull(T obj)
查看指定引用对象不是null。public static <T> T requireNonNull(T obj) { if (obj == null) throw new NullPointerException(); return obj; }
-
throws 抛出异常:将问题标识出来,报告给调用者。如果方法内通过throw抛出了编译时异常,而没有捕获处理,那么必须通过throws进行声明,让调用者去处理。 关键字 throws运用于方法声明之上,用于表示当前方法不处理异常,而是提醒该方法的调用者来处理异常(抛出异常)
修饰符 返回值类型 方法名(参数) throws 异常类名1,异常类名2…{ }
-
try-catch 捕获异常:Java中对异常有针对性的语句进行捕获,可以对出现的异常进行指定方式的处理。一般捕获你知道如何处理的异常,抛出无法处理的异常
public String getMessage()
:获取异常的描述信息,原因(提示给用户的时候,就提示错误原因。
public String toString()
:获取异常的类型和异常描述信息(不用)。
public void printStackTrace()
:打印异常的跟踪栈信息并输出到控制台。
try{
编写可能会出现异常的代码
}catch(异常类型 e){
处理异常的代码
//记录日志/打印异常信息/继续抛出异常
}
- finally 语句块
finally:有一些特定的代码无论异常是否发生,都需要执行。另外,因为异常会引发程序跳转,导致有些语句执行不到。而finally就是解决这个问题的,在finally代码块中存放的代码都是一定会被执行的。
try{
编写可能会出现异常的代码
}catch(异常类型 e){
处理异常的代码
//记录日志/打印异常信息/继续抛出异常
}finally{
//执行最终操作,例如关闭资源
}
- try-with-Resources 自动释放资源
当我们在finally语句块中需要关闭资源的时候,只要是实现了AutoCloseable
接口的类,都可以使用这个语句结构进行代替,无论执行结果如何都会在最后关闭资源 如果close
与try
都抛出异常,close抛出的异常会被抑制并增加到原来的异常,而finally做不到,所以尽量使用这个语句释放资源
try(声明资源,可以多个,例: Scanner in=new Scanner(system.in) ){
编写可能会出现异常的代码
}catch(异常类型 e){
处理异常的代码
//记录日志/打印异常信息/继续抛出异常
}
3. 断言Assert
断言机制允许在测试期间向代码中插入一些检查,而在生产代码中会自动删除这些检查
assert condition;
如果结果为false,则抛出一个AssertionError的异常
assert condition:expression;
传入一个AssertError
对象的构造器,并转换成一个消息字符串
assert a>0:a+"小于等于0";
断言的主要作用是在测试阶段向代码插入一些检查,在默认情况下断言是禁用的,可以用类加载器开启断言Xxx.class.getClassLoader().setDefaultAssertionStatus(true);
4. 自定义异常类
这里举一个例子:当restful接口需要返回错误码时,其实可以用异常代替,并用ControllerAdvice
与ExceptionHandler
对异常处理,产生对应的错误码及响应数据
- 编写异常枚举类,定义返回的状态码及错误信息
@Getter
public enum ExceptionEnum {
THIS_IS_A_EXCEPTION(400,"出现异常了"),
;
private final int code;
private final String msg;
ExceptionEnum(int code, String msg) {
this.code = code;
this.msg = msg;
}
}
- 编写自定义异常类,继承运行时异常
public class BlogException extends RuntimeException {
private final ExceptionEnum exceptionEnum;
public ExceptionEnum getExceptionEnum() {
return exceptionEnum;
}
public BlogException(ExceptionEnum exceptionEnum) {
this.exceptionEnum = exceptionEnum;
}
}
- 编写异常响应结果
@Getter
public class ExceptionResult implements Serializable {
private int status;
private String message;
private Long timestamp;
private ExceptionResult(ExceptionEnum em) {
this.status = em.getCode();
this.message =em.getMsg();
this.timestamp = System.currentTimeMillis();
}
public static ExceptionResult build(ExceptionEnum em){
return new ExceptionResult(em);
}
}
- 用ControllerAdvice与ExceptionHandler捕获异常并返回响应结果
@ControllerAdvice
@ResponseBody
public class BlogExceptionHandler {
/**
* 异常的返回结果
* @param e 异常枚举
* @return 响应体
*/
@ExceptionHandler(BlogException.class)
public ResponseEntity<ExceptionResult> handleException(BlogException e){
ExceptionEnum eEnum = e.getExceptionEnum();
return ResponseEntity.status(eEnum.getCode()).body(ExceptionResult.build(eEnum));
}
}