1. 优先使用异常而非返回错误码
    2. 设计清晰的try-catch-finally结构
    3. 异常的范围尽可能的小,尽量少用基类Exception
    4. 已检测异常的使用有利有弊。好处在于具有较好的可读性,可以明确的感知到在何处因为什么原因抛出了什么异常;坏处在于——当一个方法throw了A异常的时候,该方法的上层方法都需要throw该异常,一旦该方法throw的异常出现了变化(增加或减少或者改变),所有的上层方法都需要变更(虽然他们的方法体可能没有任何的变化,但是它们的方法签名必须要修改throw的异常列表,即出现了“修改链”),这就违反了开放闭合OCP原则。因此,谨慎使用已检测异常。同时,可以有意识的使用未检测异常,它们不会引出修改链。例如,可以使用assert断言,来抛出未检测的运行时异常,可以避免检测异常引起的修改链问题。
    5. 当一个方法可能抛出多种类型的异常时,如果代码写的不够优雅的话,调用这个方法的地方,可能会出现一个catch块链,并且每个catch块的代码可能是高度重复的。

    image.png
    image.png
    为了解决这个问题,我们可以设计一个操作类,对会抛出异常的方法进行二次封装,并在封装过程中进行异常类的转换和聚合。
    image.png
    上图中的LocalPort就是一个操作类,他的open()方法就封装了原有的ACMEPort类的open()方法,如下图所示。
    image.png
    可以看到,LocalPort类的open()方法,对多种异常类型做了转换和聚合,这就简化了上层函数的异常捕获操作。

    1. 应该学到的一种思想:将第三方API二次封装进行打包是一种良好的实践手段。通过二次封装,我们可以弱化对第三方API的细节的依赖,而只关注我们封装后的包的接口,一方面,这可以帮助我们简化变更第三方API的过程,另一方面,这有助于我们Mock第三方API,进行测试。
    2. 如果想要捕获特定的异常而放过其他异常,就要设计多个异常类。
    3. 不要使用try/catch来进行业务逻辑的处理,catch应该只是异常处理,而不应该涉及到逻辑运算。可以使用多台来解决这一问题——标准情况和异常情况下,都返回继承了同一父类(或者实现了同一接口)的两种子类对象,他们对于同一个方法有不同的实现,从而进行不同的处理,而不是抛出异常。(这叫做特例模式,Special Case Pattern)
    4. 避免在方法中返回null
    5. 避免方法接收到的参数为null。可以使用两种方式来解决:①显示判断并throw异常②使用assert,抛出运行时异常