Java的异常处理体系详解
异常处理
1、Java的异常类层次结构
其中Error表示程序运行错误
常见的错误类型有:
- OutOfMemoryError (内存溢出错误)
- StackOverFlowError (栈内存溢出错误)
- IOError (IO错误)
- 等
Exception表示程序本身可以处理的异常
其中Exception又分为
①、CheckedException (检查异常 必须在代码中显式处理 使用try catch捕获 或者 在方法上使用 throws 抛出 除了RuntimeException及其子类以外,其他的Exception类及其子类都属于受检查异常 )
常见的包括:
- IO Exception
- SQL Exception
- FileNotFoundException
- ClassNotFoundException
- 等
②、UncheckedException(非检查异常 不用显式捕获 或者 throws抛出 )
常见的包括:
- NullPointerException(空指针异常)
- ClassCastException (类型转换错误)
- IndexOutOfBoundsException (数组下标越界)
- ConcurrentModificationException(并发修改异常)
- NumberFormatException(数字转换异常)
- ArithmeticException(算数异常)
- IllegalArgumentException(参数错误)
- UnsupportedOperationException(不支持的操作 比如使用Arrays.asList生成的集合 无法使用增删改操作)
- 等
2、try-catch-finally 使用注意事项
①、try块:用于捕获异常。其后可接零个或多个 catch 块,如果没有 catch 块,则必须跟一个 finally 块。
②、当在try 块 或 catch块遇到 return语句时 finally 块会在 方法返回之前执行
③、不要在 finally 块中使用 return 语句 ,当 try 语句和 finally 语句中都有 return 语句时,try 语句块中的 return 语句会被忽略。这是因为 try 语句中的 return 返回值会先被暂存在一个本地变量中,当执行到 finally 语句中的 return 之后,这个本地变量的值就变为了 finally 语句中的 return 返回值。
示例:
1 2 3 4 5 6 7 8 9 10 11 | public int foo() { try { // some code that may throw an exception return 1 ; } catch (Exception e) { // handle exception return 2 ; } finally { return 3 ; } } |
在这个例子中,无论 try 块中的代码是否抛出异常,finally 块中的 return 3; 语句都会执行,而且会覆盖 try 块和 catch 块中的 return 语句,导致 foo() 方法始终返回3;
④、finally 块中的代码不一定会被执行 ,如果在try 或者 catch块中 出现了内存溢出或者jvm退出( System.exit(1);)等错误情况 ,对应finally 块中的代码就不会执行了。
⑤、面对必须要关闭的资源,我们总是应该优先使用 try-with-resources 而不是try-finally
try-with-resources 适用的资源包括 任何实现了 java.lang.AutoCloseable或者 java.io.Closeable 的对象
比如:Java 中类似于InputStream、OutputStream这类IO资源 需要我们使用完毕后手动关闭资源的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 | //读取文本文件的内容 BufferedReader 需要在使用完毕后手动释放资源 public static void main(String[] args) { String fileName = "C:\\Users\\Administrator\\Desktop\\数据分片.txt" ; BufferedReader reader = null ; try { reader = new BufferedReader( new FileReader(fileName)) String line; while ((line = reader.readLine()) != null ) { System.out.println(line); // 处理每一行的内容 } } catch (IOException e) { e.printStackTrace(); } finally { if (reader != null ) { try { reader.close(); } catch (IOException e) { e.printStackTrace(); } } } } //读取文本文件的内容 BufferedReader 在使用完毕后自动释放资源 (Java 7 之后支持try-with-resources ) public static void main(String[] args) { String fileName = "C:\\Users\\Administrator\\Desktop\\数据分片.txt" ; try (BufferedReader reader = new BufferedReader( new FileReader(fileName))) { String line; while ((line = reader.readLine()) != null ) { System.out.println(line); // 处理每一行的内容 } } catch (IOException e) { e.printStackTrace(); } } //读取文本文件的内容 如果有多个资源同时声明 可以使用分号分隔即可 public static void main(String[] args) { String fileName = "C:\\Users\\Administrator\\Desktop\\数据分片.txt" ; try (BufferedReader reader = new BufferedReader( new FileReader(fileName)); Scanner scanner = new Scanner( new File(fileName));) { String line; while ((line = reader.readLine()) != null ) { System.out.println(line); // 处理每一行的内容 } System.out.println( "=====>>>>>>>>>>>>>>>>>>>>>>>>" ); while (scanner.hasNext()) { System.out.println(scanner.nextLine()); // 处理每一行的内容 } } catch (IOException e) { e.printStackTrace(); } } |
⑥、不要省略异常信息的记录 在catch块中 使用日志记录关键异常信息
记录信息时尽量只写一个log.error或者log.info语句 , 因为在多线程环境下 两个相邻的日志语句不一定打印在相邻的位置
1 2 3 4 5 6 7 8 | public void aa() { try { int a = 1 / 0 ; } catch (Exception e) { // 这里一定要记录完整的异常信息 log.error( "哦,错误竟然发生了: {}" , e); } } |
3、在Web应用中如何实现全局异常处理机制
主要利用 @ControllerAdvice或者@RestControllerAdvice注解
@ControllerAdvice:
@ControllerAdvice 注解用于定义全局控制器建议,在 Spring MVC 中,控制器建议由控制器中的 @ExceptionHandler 方法、@InitBinder 方法和 @ModelAttribute 方法组成。通过 @ControllerAdvice 注解的类,可以将这些方法集中到一个地方,以便对所有控制器进行统一的异常处理、数据绑定等操作。
@RestControllerAdvice:
@RestControllerAdvice 是 @ControllerAdvice 的一个变种,用于对以 REST 风格提供 API 服务的控制器进行全局建议定义。与 @ControllerAdvice 类似,@RestControllerAdvice 注解的类可以包含全局异常处理、全局数据绑定等方法,但它专门用于 RESTful 服务,可以将异常信息转化为 JSON 格式返回给客户端。
总的来说,@ControllerAdvice 用于传统的基于视图的控制器,而 @RestControllerAdvice 用于 RESTful 服务的控制器
一般情况下 建议在Web应用中捕获自定义异常 在自定义异常中抛出自定义错误代码 并且返回给前端 方便快速排查问题 或者提示用户相关业务的错误信息
①、利用枚举类型 自定义错误代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | /** * 自定义错误类型 * */ public enum MyErrorCode { EMPTY_PARAM_ERROR( "EMPTY_PARAM_ERROR" , "远程调用错误" ), REMOTE_ERROR( "REMOTE_ERROR" , "远程调用错误" ), ; private final String code; private final String text; MyErrorCode(String code, String text) { this .code = code; this .text = text; } public String getText() { return text; } public String getCode() { return code; } } |
②、自定义异常 继承自RuntimeException
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | /** * 自定义异常 * */ public class MyException extends RuntimeException { /** * 错误代码 */ private String errorCode; /** * 格式化异常参数 */ private List<String> paramList; /** * 最常用的方法 * @param MyErrorCode 自定义错误代码 */ public MyException(MyErrorCode MyErrorCode) { this (MyErrorCode.getCode(), MyErrorCode.getText(), null ); } public MyException(String errorCode, String message) { this (errorCode, message, null ); } private MyException(String errorCode, String message, Throwable cause) { super (message, cause); this .errorCode = errorCode; } public MyException(MyErrorCode MyErrorCode, Throwable cause) { this (MyErrorCode.getCode(), MyErrorCode.getText(), cause); } public MyException(MyErrorCode MyErrorCode, List<String> params) { this (MyErrorCode.getCode(), MyErrorCode.getText(), null ); this .paramList = params; } public List<String> getParamList() { return paramList; } public void setParamList(List<String> paramList) { this .paramList = paramList; } public String getErrorCode() { return this .errorCode; } } |
③、异常处理类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RestControllerAdvice; import java.util.List; @Slf4j @RestControllerAdvice public class MyExceptionHandle { @ExceptionHandler (MyException. class ) public JsonResult<?> handleMyException(MyException e) { String message = e.getMessage(); log.error( "current web request error:" + message, e); JsonResult<Object> jsonResult = new JsonResult<>( false , message); String errorCode = e.getErrorCode(); jsonResult.setErrCode(errorCode); List<String> paramList = e.getParamList(); jsonResult.setData(paramList); return jsonResult; } /** * 处理未知异常 * * @return JsonResult */ @ExceptionHandler (Exception. class ) private JsonResult<?> handleUnKnownException(Exception e) { if ( null == e || StringUtils.isBlank(e.getMessage())) { log.error( "current web request error:" , e); return new JsonResult<Object>( false , "500" , "unknownException" , e); } String message = e.getMessage(); log.error( "current web request error:" + message, e); e.printStackTrace(); JsonResult<Object> jsonResult = new JsonResult<>( false , "500" , message, e); jsonResult.setMsg( "unknownException" ); return jsonResult; } } |
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。
微信公众号搜索 “ 脚本之家 ” ,选择关注
程序猿的那些事、送书等活动等着你
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若内容造成侵权/违法违规/事实不符,请将相关资料发送至 reterry123@163.com 进行投诉反馈,一经查实,立即处理!
相关文章
Spring MVC-@RequestMapping注解详解
@RequestMapping注解的作用,就是将请求和处理请求的控制器方法关联起来,建立映射关系。这篇文章主要给大家介绍了关于SpringMVC中@RequestMapping注解用法,文中通过实例代码介绍的非常详细,需要的朋友可以参考下2023-04-04Jpa中Specification的求和sum不生效原理分析
这篇文章主要为大家介绍了Jpa中Specification的求和sum不生效原理示例分析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪2023-08-08
最新评论