原文摘自Core Java Volume I 7th Edithon中的章节。
最近写代码碰到了很多异常处理的问题。包括在DAO层处理什么异常,抛出什么异常到Service层。 自己实现的基础方法是内部消化异常还是抛出一些异常呢?找出了core java翻了一下,顺便翻译出来做个笔记。
一。Exception handling is not supposed to replace a simple test.
异常处理机制不应该取代正常的判断逻辑。 下面第2段代码示例了一个使用异常取代非空判断的错误用法
As an example of this, we wrote some code that uses the built-in Stack class. The code in Example 11-3 tries 1,000,000 times to pop an empty stack. It first does this by finding out whether the stack is empty.
if (!s.empty()) s.pop();
Next, we tell it to pop the stack no matter what. Then, we catch the EmptyStackException that tells us that we should not have done that.
try()
{
s.pop();
}
catch (EmptyStackException e)
{
}
这一点还是比较容易做到的,没有什么可说
二。Do not micromanage exceptions.
Many programmers wrap every statement in a separate TRy block.
不要在做同一件事情的方法内,过细的划分异常处理,使得每个异常的处理代码各自为阵。
badstyle:
OutputStream out;
Stack s;
for (i = 0; i < 100; i++)
{
try
{
n = s.pop();
}
catch (EmptyStackException s)
{
// stack was empty
}
try
{
out.writeInt(n);
}
catch (IOException e)
{
// problem writing to file
}
}
goodstyle:
try
{
for (i = 0; i < 100; i++)
{
n = s.pop();
out.writeInt(n);
}
}
catch (IOException e)
{
// problem writing to file
}
catch (EmptyStackException s)
{
// stack was empty
}
理由:Think about the task that you want the code to accomplish. Here we want to pop 100 numbers off a stack and save them to a file. (Never mind why—it is just a toy example.) There is nothing we can do if a problem rears its ugly head. If the stack is empty, it will not become occupied. If the file contains an error, the error will not magically go away. It therefore makes sense to wrap the entire task in a try block. If any one operation fails, you can then abandon the task.
上面的示例展示从栈内拿出100个数字写到文件。一旦出现栈空异常或者IO写异常我们无能为力。反而是将整个过程集中到try模块,一旦捕捉到了任何操作失败抛出的异常,我们可以从全局上取消整个任务。
“一个方法只做一件事情”是另外一个面向对象的原则,如果发现一个方法里面需要分别对不同步骤进行异常的处理,而分开的异常模块会干扰到整个方法的“完整性”(类似破坏了数据库的事务一致性),这个时候可能就需要考虑重构方法了
三。Make good use of the exception hierarchy.
最大程度上使用异常体系的继承体系,精确定位异常。
!!Don't just throw a RuntimeException . Find an appropriate subclass or create your own.
!!Don't just catch Throwable . It makes your code hard to read and maintain.
不要仅仅抛出RuntimeException、Throwable等无助于事的异常。
!!don't throw them for logic errors。Callers often need to catch exceptions that they know can never happen
不要给逻辑错误抛出异常
!!Do not hesitate to turn an exception into another exception that is more appropriate.
For example, when you parse an integer in a file, catch the NumberFormatException and turn it into a subclass of IOException or MySubsystemException .
在找到更适合的异常时,千万不要犹豫~~转换异常。 比如在一个File文件操作中进行整数的转换,一个数字格式错误异常的意义远远不如给出 IOException 或者自定义的异常信息明确。
很多人领悟了异常处理的其他精髓要点,在适当的地点,丢出了“系统适当”的异常。比如上面例子,数字转换出错抛 NumberFormatException理论上是完全合适并且正确的。但是 NumberFormatException能让你联想到是在File文件操作函数里面抛出来的么?个人觉得这里输出一个MyFileWriteException更能让人定位错误,配合log日志
log.error(" MyFileWriteException---write File got NumberFormatException ");
四。Do not squelch exceptions.
不要贪图掩盖的异常
badstyle:
public Image loadImage(String s)
{
TRy
{
code that threatens to throw checked exceptions
}
catch (Exception e)
{} // so there
}
Now your code will compile without a hitch. It will run fine, except when an exception occurs. Then, the exception will be silently ignored. If you believe that exceptions are at all important, you should make some effort to handle them right.
虽然你可以得到正常的编译,并且异常也不会抛出。但是要注意到,如果是一些重要的异常,还是需要做出努力去正确的处理它们。
掩盖异常是对别人的犯罪。。。当调用一个只返回ture or flase,却不抛出任何异常的I/O函数,总会让我心里发慌。。即便定位到这个函数出错,也无法根据异常去调试
五。When you detect an error, "tough love" works better than indulgence.
发现异常,严格的处理比适当的放任更好。
Some programmers worry about throwing exceptions when they detect errors. Maybe it would be better to return a dummy value rather than throw an exception when a method is called with invalid parameters. For example, should Stack.pop return null rather than throw an exception when a stack is empty? We think it is better to throw a EmptyStackException at the point of failure than to have a NullPointerException occur at later time.
许多程序员担心抛出异常信息。也许对调用一个参数无效的函数,返回一个伪值要比抛出异常更好(e.g -1ll表示调用错误)。但是对于Stack.pop 返回null而言,抛出EmptyStackException 要比未来碰到NullPointerException 要显得更好。
”返回null总是不对的:)“Effective Java中就有这么一条。对于某些可以向外隐匿的错误通过返回-1等特殊值在一定程度上可行。返回null确实是罪过。
六。Propagating exceptions is not a sign of shame.
将异常上升到更高层次去处理,并不是一个令人害羞的事情。
Many programmers feel compelled to catch all exceptions that are thrown. If they call a method that throws an exception, such as the FileInputStream constructor or the readLine method, they instinctively catch the exception that may be generated. Often, it is actually better to propagate the exception instead of catching it:
public void readStuff(String filename) throws IOException // not a sign of shame!
{
InputStream in = new FileInputStream(filename);
. . .
}
Higher-level methods are often better equipped to inform the user of errors or to abandon unsuccessful commands.
更高级别的方法通常会有更多使用错误的信息或者中断掉不成功的调用。