百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程字典 > 正文

月薪3万以上的程序员必备技能:Java 中的异常和处理详解

toyiye 2024-08-08 00:14 15 浏览 0 评论

本文参考自阿里孤尽老师的《码出高效代码》一书的第五章,为了节省大家学习时间,在这里对重要知识进行了总结,如果有知识点不明白的可以关注作者,找作者要相关的具体学习资料(免费送上)。

处理异常需要解决的问题

  • 哪里发生异常?
  • 可以通过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代码块: 监视代码执行过程,一旦发现异常则直接跳转至catch,如果没有catch,则直接跳转至finally。
  • catch代码块: 可选执行代码,如果没有任何异常发生则不会执行;如果发现异常则可以在catch代码块中进行处理或向上抛出。
  • finally代码块: 必须执行代码块不管是否发生异常,即使发送OutOfMemoryError也会执行。通常用于处理善后清理工作。finally代码块没有执行的三种可能(很多恶心的面试官会问)
    • 没有进入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视频课程等高质量技术资料。

    相关推荐

    为何越来越多的编程语言使用JSON(为什么编程)

    JSON是JavascriptObjectNotation的缩写,意思是Javascript对象表示法,是一种易于人类阅读和对编程友好的文本数据传递方法,是JavaScript语言规范定义的一个子...

    何时在数据库中使用 JSON(数据库用json格式存储)

    在本文中,您将了解何时应考虑将JSON数据类型添加到表中以及何时应避免使用它们。每天?分享?最新?软件?开发?,Devops,敏捷?,测试?以及?项目?管理?最新?,最热门?的?文章?,每天?花?...

    MySQL 从零开始:05 数据类型(mysql数据类型有哪些,并举例)

    前面的讲解中已经接触到了表的创建,表的创建是对字段的声明,比如:上述语句声明了字段的名称、类型、所占空间、默认值和是否可以为空等信息。其中的int、varchar、char和decimal都...

    JSON对象花样进阶(json格式对象)

    一、引言在现代Web开发中,JSON(JavaScriptObjectNotation)已经成为数据交换的标准格式。无论是从前端向后端发送数据,还是从后端接收数据,JSON都是不可或缺的一部分。...

    深入理解 JSON 和 Form-data(json和formdata提交区别)

    在讨论现代网络开发与API设计的语境下,理解客户端和服务器间如何有效且可靠地交换数据变得尤为关键。这里,特别值得关注的是两种主流数据格式:...

    JSON 语法(json 语法 priority)

    JSON语法是JavaScript语法的子集。JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔花括号保存对象方括号保存数组JS...

    JSON语法详解(json的语法规则)

    JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔大括号保存对象中括号保存数组注意:json的key是字符串,且必须是双引号,不能是单引号...

    MySQL JSON数据类型操作(mysql的json)

    概述mysql自5.7.8版本开始,就支持了json结构的数据存储和查询,这表明了mysql也在不断的学习和增加nosql数据库的有点。但mysql毕竟是关系型数据库,在处理json这种非结构化的数据...

    JSON的数据模式(json数据格式示例)

    像XML模式一样,JSON数据格式也有Schema,这是一个基于JSON格式的规范。JSON模式也以JSON格式编写。它用于验证JSON数据。JSON模式示例以下代码显示了基本的JSON模式。{"...

    前端学习——JSON格式详解(后端json格式)

    JSON(JavaScriptObjectNotation)是一种轻量级的数据交换格式。易于人阅读和编写。同时也易于机器解析和生成。它基于JavaScriptProgrammingLa...

    什么是 JSON:详解 JSON 及其优势(什么叫json)

    现在程序员还有谁不知道JSON吗?无论对于前端还是后端,JSON都是一种常见的数据格式。那么JSON到底是什么呢?JSON的定义...

    PostgreSQL JSON 类型:处理结构化数据

    PostgreSQL提供JSON类型,以存储结构化数据。JSON是一种开放的数据格式,可用于存储各种类型的值。什么是JSON类型?JSON类型表示JSON(JavaScriptO...

    JavaScript:JSON、三种包装类(javascript 包)

    JOSN:我们希望可以将一个对象在不同的语言中进行传递,以达到通信的目的,最佳方式就是将一个对象转换为字符串的形式JSON(JavaScriptObjectNotation)-JS的对象表示法...

    Python数据分析 只要1分钟 教你玩转JSON 全程干货

    Json简介:Json,全名JavaScriptObjectNotation,JSON(JavaScriptObjectNotation(记号、标记))是一种轻量级的数据交换格式。它基于J...

    比较一下JSON与XML两种数据格式?(json和xml哪个好)

    JSON(JavaScriptObjectNotation)和XML(eXtensibleMarkupLanguage)是在日常开发中比较常用的两种数据格式,它们主要的作用就是用来进行数据的传...

    取消回复欢迎 发表评论:

    请填写验证码