Java 异常处理

mingzhi 7年前
   <p style="text-align:center"><img src="https://simg.open-open.com/show/3c460f1a4838be2b15e7a1f431d0ceae.jpg"></p>    <p>相信了解 Java 的人对于通过 try-catch-finally 来处理异常应该都有所了解了。但可能很多人在实际中还只是仅仅将代码包起来,然后在 catch 中输出错误信息而已。但是 Java 的异常处理其实也可以简洁、优雅。</p>    <h2>基础</h2>    <p>Java 中的异常处理都是围绕着 try-catch-finally, throw, throws 这几个展开的,也就是:</p>    <ul>     <li>try-catch-finally:捕获异常并处理。</li>     <li>throw:遇到错误的时候抛出一个异常。</li>     <li>throws:声明一个方法可能抛出的异常(所有可能抛出的异常都需要声明)。</li>    </ul>    <p>在 Java 中的异常分为 checked exception 和 unchecked exception。</p>    <p>java.lang.RuntimeException 和 java.lang.Error 类及其子类是 unchecked exception,其余的就是 checked exception 了。</p>    <p>当你在进行 API 设计时,必须要了解到异常声明也是 API 的一部分。如果你为你公开的 API 声明了可能抛出的异常,在今后很长的一段时间里你可能都甩不掉它们了。以后你要重构或进一步开发这些 API 时,不得不考虑这些异常带来的向后兼容性问题。因为,如果你在日后的版本中删除了某个异常的声明,就会造成之前用户的代码无法通过编译。</p>    <p>仔细考虑你要声明抛出的异常。</p>    <h2>异常处理</h2>    <p>异常处理的难点主要是在对于什么时候处理异常的理解上。在不同的层级上,你要考虑这个异常是不是应该在这个层级上进行处理,还是说应该继续向上抛出,甚至某些情况下还需要包装捕获到的异常,再向上抛出。</p>    <p><strong>不同抽象层级上的代码应该只声明抛出同一层级上的异常。</strong></p>    <p>就像处理界面的代码不应该还会捕获处理数据库操作的异常一样。 为了避免这个问题,更高层次的实现需要捕获低层次的异常,包装之后再抛出属于更高层次的异常。这种做法被称作:Exception translation。</p>    <pre>  <code class="language-java">try {      ...  } catch(LowerLevelException e) {      throw new HigherLevelException(...);  }</code></pre>    <p>当然最完美的情况还是完美的层次设计,在调用低层级的方法之前确保它们无论如何都能成功执行,从根本上避免低层抛出异常。实在避免不了,再使用 exception translation。</p>    <p>在具体处理异常的地方,应当使 try-catch 块尽可能的小,catch 尽可能具体的异常。千万不要 catch Exception 这么宽泛的异常之后就不管了。尝试把 try-catch 作为程序流程控制的一部分。</p>    <p>比如:</p>    <pre>  <code class="language-java">String parm;  try {      param = jsonObj.getString("parm");  } catch (JSONException e) {      e.printStackTrace();      param = "default value";    // 设置一个默认值。  }  // Use param.</code></pre>    <p>这也隐含了一个准则: <strong>不要忽略异常</strong> 。忽略异常最简单的一个方法就是使用一个空的 catch。即使你确定什么都不需要做,至少也要包含一条记录,解释为什么可以什么都不做。</p>    <p>如果你需要自己创建异常,请将对异常的设计放在与程序设计同样的地位。有的开发者可能会用一个大而全的异常类来表示各种不同类型的错误,只用错误信息来区分不同的错误。这种异常处理方式一方面是不够优雅,另一方面是当你需要进行 exception translation 时很难对这种大而全的异常进行再包装。</p>    <p>你应该仔细设计异常的层次结构,根据不同的抽象定义不同的异常类,并在异常类中包含尽量丰富的信息。对于异常提供的信息来说,是程序的内部错误,要和展示给用户的错误提示区分开来。因此,程序需要保证在和用户交互的层次上,捕获所有的异常,并生成相应的面向用户的错误提示。</p>    <p>这里只分享了异常处理中的一些原则和思想,如果想了解具体的实践方法可以阅读最后的参考资料。: )</p>    <p>参考资料:</p>    <ul>     <li><a href="/misc/goto?guid=4959727691840280906" rel="nofollow,noindex">Exception handling </a></li>     <li>深入理解 Java 7:核心技术与最佳实践</li>     <li>Effective Java (2nd edition)</li>    </ul>    <p> </p>    <p>来自:https://zhuanlan.zhihu.com/p/24043941</p>    <p> </p>