异常及处理

来源:互联网 发布:java 将字符串格式化 编辑:程序博客网 时间:2024/05/23 13:58
Java 中的异常

什么是异常?

– Java中所有的异常都是Throwable类的子类
– 异常是Java程序用来指示一个错误信息的事件
– Java中的异常分为两大类:
• Error——系统异常,这类异常通常不是程序员或者用户可以控制的,例如OutOfMemoryError,内存
不足错误,或者我们以前看到过的堆栈溢出错误
– 这类异常通常不需要捕获,在运行中遇到这类情况的时候,应该重新规划程序以避免这类错误
• Exception——由于程序或调用引起的异常状况,这类异常分为两大类:
– 普通异常——Exception或其子类(除RuntimeException)
– 运行时异常——RuntimeException或其子类

异常的捕获
– Error
• 不应捕获Error,这类错误应该通过程序结构、设计等进行处理以防止出错
• 常见的例子:
– OutOfMemoryError——内存不足异常,通常是创建了过多的对象或者内存过度碎片化引起的,可以通
过对象池等方式解决
– StackOverflowError——堆栈溢出错误,通常由递归调用引发,当然也可能是因为函数调用嵌套过多引
起堆栈内存不足
– RuntimeException
• 通常不应捕获该类异常,而是直接通过修改程序、调用等进行处理以防止异常的出现
• 该类异常通常是可以避免的
• 常见的例子:
– NullPointerException——空指针异常,通常是忘了实例化对象或者没有对对象是否为null进行检测
– ArithmeticException——数学计算异常,例如被0除
– IllegalArgumentException——函数调用时参数类型不对
– Exception——普通异常

Exception的捕获
– 通过try {} catch {}进行捕获
– 每个try{}内部调用可能引发异常的代码,catch进行捕获
– 每个try{}可以跟多个catch(Exception类 Exception变量名){}
– Catch的调用是按照顺序进行调用的,只要第一个匹配,就不会执行以后的catch,即使以后
的catch也匹配
• 例如:
try {
} catch (Exception e) {
} catch (java.io.IOExceptoin e) {
} catch (java.io.FileNotFoundException fe) {

•上述代码中,如果try{}中抛出了一个FileNotFoundException,由于该异常继承自
IOException,而IOException又是Exception的子类,所以第一个catch就已经匹配了,后面两
个不会执行,一定要按照FileNotFoundException, IOException, Exception的顺序进行捕获
• 也可以捕获Throwable,即所有类型的异常


 finally{}——在catch异常之后,进行清理工作,finally会在捕获异常之后被调用,因
此往往用来进行清理工作,例如关闭已经打开的文件或数据库连接,终止已经启动的
线程等等
每个try后面必须有一个或者多个catch,最后可以有一个finally,如果最后有finally,
中间可以没有catch
 Java 7开始,一个catch可以处理多个Exception,以减少代码量:
– … catch (FileNotFoundException | SQLException ex) {}这里ex可以是
FileNotFoundException或者SQLException


 异常是如何产生的?
– Java API或者JVM本身可以抛出异常
– 用户自己编写的方法可以抛出异常
 如何在用户自己的方法中抛出异常
– 可以抛出Java API已经定义的异常,例如ArrayIndexOutOfBoundsException,
– 或者抛出用户自定义异常
– 用户自定义异常通常继承自Exception,不要去直接实现Throwable或者继承自
RuntimeException,除非你非常确定自己在做什么
– 使用throw Exception实例抛出异常
• 例如:throw new FileNotFoundException();
– 如果是Error或者RuntimeException,则不需要在方法中声明
– 如果是普通Exception,则需要在方法中声明:
public class UserException extends Exception {…}
public void calculate() throws UserException
• 异常抛出声明的顺序也要注意从子类到父类的顺序

 在哪里捕捉异常?
– 对于抛出异常的方法,可以在调用它的方法中用try/catch进行捕捉
– 也可以不在调用中捕捉,则调用的方法声明时必须抛出相应的普通Exception
 怎样捕捉才是正确的
– Exception是Java编程中重要的组成部分,学会使用、读取Exception信息是掌握Java编程的
必备技能之一
– 不要这么做:
• try{…} catch(Exception e){…}——不要一下子处理所有的异常,不同的异常行为可能需要不同的处理
• try{…} catch(Exception e){ throw e; }——不要重新扔出原来的异常,这没有任何意义
• try{…} catch(Exception e){ return 1; }——捕捉了异常之后不要不进行处理,你会丢掉异常的有用信息
• try{…} catch(Exception e){ System.out.println(e.getMessage());}——不要只打印异常的消息部分,
最重要的是异常的堆栈信息,而不仅仅是消息部分


 异常的处理:
– 记住,使用e.printStackTrack(),或者如果你使用log4j一类的日志工具,使用log.error(e)来
打印异常的堆栈信息
– 堆栈信息能够提供出现异常时的API调用顺序,这对于判断异常是如何出现的具有重大意义
• 你希望得到的错误提示是这样的:
– java.lang.StringIndexOutOfBoundsException
• 还是这样的:
java.lang.StringIndexOutOfBoundsException: String index out of range: 9
at java.lang.StringBuffer.charAt(Unknown Source)
at PrintStack.main(PrintStack.java:13)
• 堆栈信息的读取应该这样:
– 从下到上,是方法调用的顺序,以上面的例子为例,首先调用的是PrintStack.main,在其第13行,
调用了StringBuffer.charAt(),这个方法触发了上述的异常,
– 有了这个信息,就可以很快的判断在调用StringBuffer.charAt()时需要做范围的判断,防止越界
最好的方式,是通过日志工具进行异常以及其它信息的记录,在程序发生错误的时候
快速通过日志文件判断可能出错的原因以及位置
原创粉丝点击