网站首页 > 精选教程 正文
本文参考自阿里孤尽老师的《码出高效代码》一书的第五章,为了节省大家学习时间,在这里对重要知识进行了总结,如果有知识点不明白的可以关注作者,找作者要相关的具体学习资料(免费送上)。
处理异常需要解决的问题
可以通过try-catch捕获异常。不建议用try-catch捕获大代码块,同时捕获异常时要分清稳定代码(无论如何都不会出错的代码,如int i = 0)和非稳定代码(有可能出错的代码。如:Integer.valueOf(String s)转换失败时抛出NumberFormatException异常)。
- throw:用于方法内抛出具异常类对象的关键字。
public static Long getDateTime(String time) throws ParseException { if (org.apache.commons.lang.StringUtils.isEmpty(time) || time.length() != 8) { throw new BizException("单元格日期为空"); } SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd"); dateFormat.setLenient(false); return dateFormat.parse(time).getTime(); }
- throws:用在方法签名上,表示方法调用者可以通过此方法声明向上抛出异常对象。
public static Integer valueOf(String s) throws NumberFormatException { return Integer.valueOf(parseInt(s, 10)); }
如果异常在当前方法处理能力范围之内则没必要对外透出,直接捕获并做相应处理即可。否则向上抛出,由上层方法或框架来处理。
禁止异常捕获后什么都不做或打印一行日志了事。
- 方法内处理:需要根据业务场景定制处理,如重试、回滚等操作。
- 向上抛异常:需要在异常对象中添加上下文参数、局部变量、运行环境等信息,有利于排查问题。
异常分类
JDK中定义了一套完整的异常机制,所有异常都是Throwable的子类,分为Error(致命异常)和Exception(非致命异常)。Error是一种非常特殊的异常类型(程序无法处理,只能人工介入),它的出现标识着系统发生了不可控的错误,如StackOverflowError、OutOfMemoryError。Exception又分为checked异常(受检异常)和unchecked(非受检异常)。
- checked异常:需要在代码中显式处理的异常,否则会编译出错。如:SQLException、ClassNotFoundException等。checked异常又可细分为:
- 无能为力、引起注意型。即程序无法处理,如字段超长等导致的SQLException。处理方式:保存异常现场,工程师介入。
- 力所能及、坦然处置型。如发送未授权异常,程序可以直接跳转至权限申请页面。
- unchecked异常:运行时异常,都继承自RuntimeException,不需要显式的捕获和处理。unchecked异常又可细分为:
- 可预测异常:包括IndexOutOtBoundsException、NullPointerException等异常。基于代码性能和稳定性考虑,此类异常不应该被产生或抛出,应该提前做好边界检查、空指针判断等处理。
- 需捕捉异常:如使用Dubbo框架RPC调用产生的远程调用超时异常DubboTimeoutException,客户端必须显式处理(重试、降级处理等),不能因为服务器异常导致客户端不可用。
- 可透出异常:指框架或系统产生的且会自行处理的异常,而程序无须关心。
异常分类结果图如下:
最后,处理异常时,要明确该异常属于哪种异常类型,是需要调用方关注并处理的checked异常,还是由更高层次框架处理的unchecked异常。无论哪类异常,如果需要向上抛出,推荐根据当前场景自定义具有业务含义的异常。(不推荐直接使用RuntimeException、Exception等没有业务含义的异常类,同时为了避免异常泛滥,推荐优先使用业界或团队定义过的异常)
try代码块
try-catch-finally是处理异常的三部剧。当存在 try 时,可以只有 catch 代码块, 也可以只有 finally 代码块,就是不能单独只有 try 这个光杆司令。
- 没有进入try代码块。
- 进入try代码块,但是代码运行中出现死循环或死锁状态。
- 进入try代码块。但是执行了System.exit()操作。
注意: finally是在return表达式运行后执行的,此时return的结果已经被缓存起来,待finally代码块执行结束后再将之前暂存的结果返回。示例代码如下:
//结果返回1 public int getFinallyResult(){ int a = 0; //1 初始化变量 try{ a = 1; //2 变量重新赋值 return a; // 3 将a的值缓存 5将第3步缓存的值返回 }finally { a++; //4 将a值进行a++操作后a的值为2 } }
禁止finally代码块中使用return语句。因为在finally中使用return会使得返回值的判断变得复杂,不可控。
try代码块与锁关系:
//错误示列 Lock lock = new ReentrantLock(); try{ //lock.lock()放在try{}中,如果lock.lock()加锁失败,则会导致lock.unlock()解锁失败。 //将lock.lock()放在try{}外第一行即可,这样lock.lock()加锁失败就失败,不会触发 //lock.unlock()。 lock.lock(); //处理一些工作 }finally { lock.unlock(); } //正确示列 Lock lock = new ReentrantLock(); lock.lock(); try{ //处理一些工作 }finally { lock.unlock(); }
//正确示列 Lock lock = new ReentrantLock(); lock.lock(); try{ //处理一些工作 }finally { lock.unlock(); }
最后:Lock、ThreadLocal、InputStream 等这些需要进行强制释放和清除的对象都得在 finally 代码块中进行显式的清理,避免产生内存泄漏或资源消耗。
异常的抛与接
传递异常信息的方式是通过抛出异常对象,还是把异常信息转成信号量封装在特定对象中,这需要方法提供者和方法调用者之间达成契约,只有大家都照章办事,才不会产出误解。推荐对外提供的开放接口使用错误码,公司内部跨应用远程服务调用优先考虑使用 Result 对象来封装错误码、错误描述信息;而应用内部则推荐直接抛出异常对象。
方法是否直接返回null: 不强制直接返回空集合或者空对象等,但是必须添加注释充分说明什么情况下会返回null值。防止NPE一定是调用方的责任,需要调用方进行事先判断。
END
点赞+转发+关注,私信作者“读书笔记”即可获得BAT大厂面试资料、高级架构师VIP视频课程等高质量技术资料。
- 上一篇: Java异常处理详解
- 下一篇: 太简单了!这套Java异常处理的总结,80%的人都没看过
猜你喜欢
- 2024-11-20 Java中的异常
- 2024-11-20 小白也能看懂的Java异常处理机制
- 2024-11-20 JVM是如何处理各种异常的呢?
- 2024-11-20 Java异常之异常处理类详解和代码举例
- 2024-11-20 第25天|Java入门有野,异常处理
- 2024-11-20 java安全编码指南之:异常处理
- 2024-11-20 解读Java编程思想--异常处理
- 2024-11-20 Java中异常处理机制的详细解析及其优化示例代码
- 2024-11-20 学习java, 需要知道的异常处理
- 2024-11-20 java异常处理
你 发表评论:
欢迎- 04-11Java面试“字符串三兄弟”String、StringBuilder、StringBuffer
- 04-11Java中你知道几种从字符串中找指定的字符的数量
- 04-11探秘Java面试中问的最多的String、StringBuffer、StringBuilder
- 04-11Python字符串详解与示例(python字符串的常见操作)
- 04-11java正则-取出指定字符串之间的内容
- 04-11String s1 = new String("abc");这句话创建了几个字符串对象?
- 04-11java判断字符串中是否包含某个字符
- 04-11关于java开发中正确的发牌逻辑编写规范
- 最近发表
-
- Java面试“字符串三兄弟”String、StringBuilder、StringBuffer
- Java中你知道几种从字符串中找指定的字符的数量
- 探秘Java面试中问的最多的String、StringBuffer、StringBuilder
- Python字符串详解与示例(python字符串的常见操作)
- java正则-取出指定字符串之间的内容
- String s1 = new String("abc");这句话创建了几个字符串对象?
- java判断字符串中是否包含某个字符
- 关于java开发中正确的发牌逻辑编写规范
- windows、linux如何后台运行jar(并且显示进程名)
- 腾讯大佬私人收藏,GitHub上最受欢迎的100个JAVA库,值得学习
- 标签列表
-
- nginx反向代理 (57)
- nginx日志 (56)
- nginx限制ip访问 (62)
- mac安装nginx (55)
- java和mysql (59)
- java中final (62)
- win10安装java (72)
- java启动参数 (64)
- java链表反转 (64)
- 字符串反转java (72)
- java逻辑运算符 (59)
- java 请求url (65)
- java信号量 (57)
- java定义枚举 (59)
- java字符串压缩 (56)
- java中的反射 (59)
- java 三维数组 (55)
- java插入排序 (68)
- java线程的状态 (62)
- java异步调用 (55)
- java中的异常处理 (62)
- java锁机制 (54)
- java静态内部类 (55)
- java怎么添加图片 (60)
- java 权限框架 (55)
本文暂时没有评论,来添加一个吧(●'◡'●)