“开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 27 天,点击查看活动详情”
前言
exception
是java中的完美机制之一。
方法在执行的过程中由于某种原因而不能正常的达到目的,这样的现象称为异常。
本文主要介绍异常的处理方式、异常的分类、自定义异常。
I 异常的处理方式
1.1 抛异常
在发生的方法行为中,将异常传递出去,交由其他地方处理。
修饰符 返回值类型 方法名(参数列表) throws 异常类名,异常类名{
//类体
}
在方法定义中声明throws异常类名。
1.2 捕捉异常
异常在方法中发生后,立即对其采取处理。
try{
//语句块
}catch(异常类名 变量名){
//异常的处理,替代方案
}catch(异常类名 变量名){
//异常的处理,替代方案
}finally{
//代码块
}
- 捕捉异常的优先顺序:
catch块中是需要捕捉的异常,捕捉按照小类型到大类型的顺序捕捉,不能倒置;
如果捕捉的异常存在继承关系,应该先捕捉小类型,再捕捉大类型的异常。若不存在继承关系,那么无捕捉的优先顺序。
try,
catch
,finally
的个数:
try只能有一个;catch可以有,也可以没有;finally也可以有没有;
但catch和finally至少出现一个。
catch
块的执行顺序:
如果在捕捉异常的过程中,若有多个catch块,按照从上到下的顺序执行catch块;
若有一个catch块被执行,其他catch就不会被执行;finally总是会被执行。
1.3 抛异常和捕获异常的区别
- 捕获异常:当前行为发生异常之后,能够寻求替代方案,继续完成当前的行为。
- 抛异常:当行为发生异常之后,在当前行为中,无法寻找替代方案,需要将异常抛出。
1.4 产生异常
throw new 异常类名();
有很多的异常在API中已产生
发生异常,代码以后的执行顺序:
- 如果使用
try{}catch
方式处理异常,当前代码位于try块中;如果当前代码发生了异常后,在try块且位于当前代码之后的代码不会被执行,直接进入catch块中;执行完catch块,继续执行后面的代码。 - 若使用throws处理异常时,当前代码在执行过程中发生异常之后,位于当前代码以后的所有语句都将不会被执行。
package com.csuinfosoft.grammer.exceptionDemo;
/**
*
* @author 工号:ios逆向
* try {}里有一个return语句,那么紧跟在这个try后的finally {}里的code会被执行,
* finally {}里的code在return执行后,finally {}执行完在返回结果。
* 具体看test1和test2的区别。
* 如果finally,有return语句,就直接结束方法。
* 如果finally,没return语句,就再次返回return处来结束方法。
*/
public class ExceptionDemo {
public static void main(String[] args) {
System.out.println(ExceptionDemo.test1());//1
System.out.println(ExceptionDemo.test2());//2
}
static int test1(){
int x = 1;
int y=1;
try
{
return x;//执行后,跳到finally执行。此时放回结果已经压入的栈中,结果为1
}
finally
{
x=x+1;//finally执行完又跳回来执行return语句。此时的局部变量x=2.
}
}
static int test2(){
int x = 1;
try
{
return x;//执行后,跳到finally执行。此时放回结果已经压入的栈中,结果为1
}
finally
{
return x=x+1;//finally执行完,直接返回结果。此时再次向栈中压入放回结果2。
}
}
}
II 异常分类
2.1 异常的选择
- 跟内存有关的异常,通常使用运行时异常;
- 跟内存以外有关的异常,通常使用编译时异常。
2.2 编译时异常与运行时异常的语法检查区别
- 编译时异常
- 编译时异常的javac过程的语法检查步骤:
a. 检查代码中是否有异常产生 b. 检查异常是否被处理 注:以上两步缺一不可,如果缺失就会提示语法错误。
- 编译时异常,如果没有产生异常,就不能去捕捉。在IDE中,如果产生捕捉时将提示如此信息:
Unreachable catch block for ActivationException. This exception is never thrown from the try statement body。
- 运行时异常
- 运行时异常,可以在没产生异常时,在代码中可以进行捕获。
- 因为运行时异常不参与语法检查, 运行时异常无论在代码中产生异常或者处理异常都可通过语法检查。
III 自定义的异常
目的:能够给用户提供更准确的提示信息,改善用户体验。
3.1 如何自定义异常?
- 需要继承异常父类(Exception或RuntimeException)
- 提供对应的构造器
- 在对应的构造器调用父类对应的构造器
3.2 自定义异常示例
package exception;
/**
*
* @author 张坤楠
*自定义DAO层的异常,一般DAO层的异常,都封装成统一的DAOException在抛向BIZ层。
*这里定义的是编译时异常。
*/
public class DAOException extends Exception {
/**
* 构造详细消息为 null 的新异常
*/
public DAOException() {
super();
}
/**
*
* @param message
* @param cause
* @param enableSuppression
* @param writableStackTrace
*/
public DAOException(String message, Throwable cause,
boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
}
/**
* 构造带指定详细消息和原因的新异常。
* @param message
* @param cause
*/
public DAOException(String message, Throwable cause) {
super(message, cause);
}
/**
* 构造带指定详细消息的新异常。
* @param message
*/
public DAOException(String message) {
super(message);
}
/**
* 根据指定的原因和 (cause==null ? null : cause.toString()) 的详细消息构造新异常(它通常包含 cause 的类和详细消息)。
* @param cause
*/
public DAOException(Throwable cause) {
super(cause);
}
}
IV http请求返回详细错误信息
@ExceptionHandler
拦截500服务器错误,自定义数据回前端。
@ControllerAdvice
public class CommonExceptionAdvice {
@ResponseBody
@ExceptionHandler(value = {Exception.class})
public ServerResponse globalError(HttpServletRequest request, Exception e) {
if (userSentinel) {
Tracer.trace(e);
}
// 输出控制台打印日志
log.error(CommonMethod.getTrace(e));
// 返回前端提示信息
//return ServerResponse.createByError("500", "未知错误!");
//开发阶段先返回详细错误信息
return ServerResponse.createByError("500", CommonMethod.getTrace(e));
}
}
获取详细错误信息
public static String getTrace(Throwable t) {
StringWriter stringWriter = new StringWriter();
PrintWriter writer = new PrintWriter(stringWriter);
t.printStackTrace(writer);
StringBuffer buffer = stringWriter.getBuffer();
return buffer.toString();
}