Effective Java 2 读书笔记 第9章 异常

本文详细阐述了异常处理的最佳实践,包括如何合理使用异常、区分受检异常与运行时异常、避免不必要的受检异常使用、优先使用标准异常、抛出与抽象相对应的异常、每个方法的异常文档、细节消息的丰富性、失败原子性的实现,以及如何正确处理异常,以提高代码质量和可维护性。

第57条:只针对异常的情况才使用异常

  1. 异常应该只用于异常的情况下,不该用于正常的控制流
    // Horrible abuse of exceptions. Don't ever do this!
    
    
    try {
    
    
    int i = 0;
    
    
    while(true)
    
    
    range[i++].climb();
    
    
    } catch(ArrayIndexOutOfBoundsException e) {
    
    
    }
     
  2. 设计良好的API不应该强迫它的客户端为了正常的控制流而使用异常,可以提供状态测试(hashNext())或者可识别的返回值(return null)。

第58条:对可恢复的情况使用受检异常,对编程错误使用运行时异常

java有三种可抛出的结构(throwable),受检的异常(checked exception)、运行时异常(run-time exception)和错误(error)。

  1. 如果期望调用者能够适当地恢复,对于这种情况就应该使用受检的异常。或者在catch中处理,或者传播出去,如sql,io Exception。这样的异常可以提供辅助方法,使得调用者得到一些有助于恢复的信息。
  2. 用运行时异常来表明编程错误。大多数运行时异常都是前提违例(precondition violation)。就是没有遵守API规范建立的约定。如数组下标不能越界
  3. 情况并不是绝对的,如考虑资源枯竭的情形,可能是因为程序的错误引起的,如分配了不合理的大叔组,如果资源是因为临时的短缺或者临时需求太大所造成的,这种情况可能就是可恢复的。API设计者需要判断这样的资源是否允许回复。如果你相信一种情况可能允许恢复,那么使用受检异常,否则使用运行时异常。不清楚,最好使用未受检的异常。

第59条:避免不必要第使用受检的异常

如果正确地使用API并不能阻止这种异常条件的产生,并且一旦产生异常,使用API的程序员可以立即采取有用的动作,这种负担就被认为是正当的。除非这两个条件都成立,否则更适合于使用未受检的异常。

理解不深刻

第60条:优先使用标准的异常

追求重用,异常也不例外。

  1. 重用异常的好处:
    1. 使你的API更加易于学习和使用,因为它与程序员已经熟悉的习惯用法是一致的
    2. 可读性更好
    3. 异常类越少,内存印迹就越小,装载这些类的时间开销也越小
  2. 常用异常

    常用异常

  3. 选择重用哪个异常并不总是那么精确,使用场合不排斥。

第61条:抛出与抽象相对应的异常

  1. 更高层的实现应该捕获低层的异常,同时抛出可以按照高层抽象进行解释的异常,即异常转译(Exception translation)
    // Exception Translation
    
    
    try {
    
    
    // Use lower-level abstraction to do our bidding
    
    
    ...
    
    
    } catch(LowerLevelException e) {
    
    
    throw new HigherLevelException(...);
    
    
    }
     
  2. 异常链,低层的异常对于调试导致高层异常的问题有帮助的时候使用
    // Exception Chaining
    
    
    try {
    
    
    ... // Use lower-level abstraction to do our bidding
    
    
    } catch (LowerLevelException cause) {
    
    
    throw new HigherLevelException(cause);
    
    
    }
     
  3. 尽管异常转译与不加选择第从底层传递异常的做法相比有所改进,但是它也不恩那个被滥用。如果可能,处理来自低层异常的最好做法是,在调用低层方法之前确保它们会成功执行,从而避免它们抛出异常。如在给低层传递参数之前,检查高层参数有效性,从而避免低层抛出异常
  4. 如果无法避免低层异常,次选是,让更高层来悄悄绕开这些异常,从而将高层方法的调用者与低层的问题隔离开来。如使用java.util.logging将异常记录下来。

第62条:每个方法抛出的异常都要有文档

  1. 始终要单独地声明受检的异常,并且利用Javadoc@throws标记,准确第记录下抛出每个异常的条件,如果一个方法可能抛出多个异常类,则不要使用“快捷方式”声明它会抛出这些异常类的某个超类。永远不要声明一个方法“throws Exception“,或者更糟的是声明”throws Throwable",这是非常极端的例子。这样的声明不仅没有指导信息,反而妨碍使用,因为它掩盖了该方法可能抛出的任何其他任何异常。
  2. 使用Javadoc的@throws标签记录下一个方法可能抛出的每个未受检异常,但是不要使用throws关键字将未受检的异常包含在方法的声明中。
  3. 使用API的程序员必须知道哪些异常是需要受检的,那么是不需要受检的,这很重要,因为这两种情况下他们的责任不同。
  4. 注意:类被修订之后,可能会出现新的异常,尽管以前并没有声明这些异常
  5. 如果一个类中的许多方法出于同样的原因而抛出同一个异常,在该类的文档注释中对这个异常建立文档,这是可以接受的。

总之,要为每个方法所能抛出的每个异常建立文档。要为每个受检异常提供单独的throws子句。不要为未受检的异常提供throws子句。

第63条:在细节消息中包含能捕获失败的消息

为了捕获失败,异常的细节信息应该饱和所有“对该异常有贡献”的参数或者域的值,虽然java平台类库没有广泛这么做,但是值得大力推荐,它使得程序员更加易于抛出异常以捕获失败。

第64条:努力使失败保持原子性

一般而言,失败的方法调用应该使对象保持在被调用之前的状态。具有这种熟悉的方法被成为具有失败原子性(failure atomic)。

  1. 最简单的办法莫过于设计一个不可变的对象,如果对象不可变,失败原子性就是显然的了
  2. 对于在可变对象上执行操作的方法,获得原子性最常见的办法是,在执行操作之前检查参数的有效性。如
    public Object pop() {
    if (size == 0)
    throw new EmptyStackException();
    Object result = elements[--size];
    elements[size] = null; // Eliminate obsolete reference
    return result;
    }
     
  3. 做恢复代码,回滚
  4. 在对象的临时拷贝上进行操作,完成之后在用临时拷贝中的结构代替对象的内容。

一般而言,作为方法规范的一部分,产生任何异常都应该让对象保持在该方法调用之前的状态。如果违反这条规则,API文档就应该清楚地指明对象将会处于什么样的状态。

第65条:不要忽略异常

  1. 当api的设计者声明一个方法将抛出某个异常的时候,他们等于正在试图说明某些事情,因此不要忽略它。
  2. 空的catch会时异常达不到应有的目的,至少,catch块也应该保护一条说明,解释为什么可以忽略这个异常

内容概要:文以“智能网页数据标注工具”为例,深入探讨了谷歌浏览器扩展在毕业设计中的实战应用。通过开发具备实体识别、情感分类等功能的浏览器扩展,学生能够融合前端开发、自然语言处理(NLP)、本地存储与模型推理等技术,实现高效的网页数据标注系统。文中详细解析了扩展的技术架构,涵盖Manifest V3配置、内容脚本与Service Worker协作、TensorFlow.js模型在浏览器端的轻量化部署与推理流程,并提供了核心代码实现,包括文本选择、标注工具栏动态生成、高亮显示及模型预测功能。同时展望了多模态标注、主动学习与边缘计算协同等未来发展方向。; 适合人群:具备前端开发基础、熟悉JavaScript和浏览器机制,有一定AI模型应用经验的计算机相关专业本科生或研究生,尤其适合将浏览器扩展与人工智能结合进行毕业设计的学生。; 使用场景及目标:①掌握浏览器扩展开发全流程,理解内容脚本、Service Worker与弹出页的通信机制;②实现在浏览器端运行轻量级AI模型(如NER、情感分析)的技术方案;③构建可用于真实场景的数据标注工具,提升标注效率并探索主动学习、协同标注等智能化功能。; 阅读建议:建议结合代码实例搭建开发环境,逐步实现标注功能并集成本地模型推理。重点关注模型轻量化、内存管理与DOM操作的稳定性,在实践中理解浏览器扩展的安全机制与性能优化策略。
基于Gin+GORM+Casbin+Vue.js的权限管理系统是一个采用前后端分离架构的企业级权限管理解决方案,专为软件工程和计算机科学专业的毕业设计项目开发。该系统基于Go语言构建后端服务,结合Vue.js前端框架,实现了完整的权限控制和管理功能,适用于各类需要精细化权限管理的应用场景。 系统后端采用Gin作为Web框架,提供高性能的HTTP服务;使用GORM作为ORM框架,简化数据库操作;集成Casbin实现灵活的权限控制模型。前端基于vue-element-admin模板开发,提供现代化的用户界面和交互体验。系统采用分层架构和模块化设计,确保代码的可维护性和可扩展性。 主要功能包括用户管理、角色管理、权限管理、菜单管理、操作日志等核心模块。用户管理模块支持用户信息的增删改查和状态管理;角色管理模块允许定义不同角色并分配相应权限;权限管理模块基于Casbin实现细粒度的访问控制;菜单管理模块动态生成前端导航菜单;操作日志模块记录系统关键操作,便于审计和追踪。 技术栈方面,后端使用Go语言开发,结合Gin、GORM、Casbin等成熟框架;前端使用Vue.js、Element UI等现代前端技术;数据库支持MySQL、PostgreSQL等主流关系型数据库;采用RESTful API设计规范,确保前后端通信的标准化。系统还应用了单例模式、工厂模式、依赖注入等设计模式,提升代码质量和可测试性。 该权限管理系统适用于企业管理系统、内部办公平台、多租户SaaS应用等需要复杂权限控制的场景。作为毕业设计项目,它提供了完整的源码和论文文档,帮助学生深入理解前后端分离架构、权限控制原理、现代Web开发技术等关键知识点。系统设计规范,代码结构清晰,注释完整,非常适合作为计算机相关专业的毕业设计参考或实际项目开发的基础框架。 资源包含完整的系统源码、数据库设计文档、部署说明和毕
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值