csusky

常用链接

统计

最新评论

JAVA中的异常处理

在JAVA中,如果某个方法不能够按照正常的途径完成它的任务,就可以通过另外一个途径退出方法。在这种情况下,方法并不立刻返回,而是抛出一个封装了错误信息的对象。需要注意的是,这个方法将会立刻退出,且并不返回正常情况下的值。此外,调用这个方法的代码也将无法执行,取而代之的是,异常处理机制开始搜索能够处理这种错误条件的异常处理器。

如果在子类中覆盖了超类的一个方法,那么子类方法声明的已检查异常不能超过超类方法中声明的异常围。(也就是说子类中抛出的异常范围更小或者根本不抛出异常)。需要说明的是,如果超类方法没有抛出任何异常,子类也不能抛出任何已检查异常。例如,如果覆盖JComponent.paintComponent()方法,那么    由于超类中没有抛出任何异常,所以自定义的paintComponent()方法也不能抛出任何异常。

如何抛出异常:
譬如在读一个输入流时,如果期待的字节数为1024,而当读到700字节的时候遇到一个EOF信号,这是我们未预期的,正是我们要抛出的异常,下面就是抛出改异常的语句

1String readData() throws EOFException {
2   while ({
3      if(!in.hasNext()) {
4          if(n<len)
5            throw new EOFException();
6     }
  
7  }

8}

这是抛出已存在标准的异常,步骤为:
1.找到一个合适的异常类
2.创建该类的对象
3.将异常抛出
一旦抛出异常,该方法就不可能返回到调用者,这就意味着不必为返回的默认值或错误代码担忧了。

在程序中可能会遇到任何标准异常都无法正确描述清楚的问题,这时候就需要定义自己的异常类,定义自己的异常类需要继承自Exception 或者其子类,如继承自IOException  一般要为自定义的Exception定义两个构造函数,一个是默认的无参的构造函数,另一个是带一个描述详细错误信息String的构造函数(超类的toString()方法会打印出这些详细信息。

1public class MyException extends IOException {
2
3    MyException () {}
4    
5    MyException (String info) {
6       super(info);
7   }

8}

现在就可以像使用标准Exception类一样使用自定义的Exception类了

1String readData() throws MyException {
2   while () {
3      if(!in.hasNext()) {
4          if(n<len)
5            throw new MyException();
6    }
  
7 }

8}

可以用超类Throwable类的getMessage方法得到详细的错误描述信息。或者toString()方法打印该信息。

捕获异常:
如果语句exp1有可能抛出一个异常,或者说是调用了能够抛出一个异常的方法,那么我们可以在程序中捕获该异常

1try {
2 exp1;
3 exp2;
4 .
5
6}
 catch(Exception e) {
7   e.
8}

9

或者是并不捕获,再次抛出该异常

再次抛出异常,异常链:
可以在catch块中再次抛出新的异常,这样可以隐藏原始的错误细节

1catch(SQLException sqle) {
2    throw new ServletException("caused by SQLException "+e.getMessage());
3}

另一种更好的方法
既抛出高级的异常,又不会丢失原始的异常信息。

1}catch(SQLException sqle) 
2    Throwable ta=new ServletException("caused by SQLException");
3    ta.setCause(e);
4    throw ta;
5}

6当捕获抛出的异常ta时,可以用ta.getCause(),得到原始的异常


finally子句,发生三种情况时,会执行finally子句
1.try代码正常执行
2.try代码抛出一个在catch子句中捕获的异常
3.try代码抛出一个未在catch子句中捕获的异常
就是说无论异常如何,finally子句中的代码都会执行
一般把一些资源回收的工作交给finally子句

最好把try-catch块和try-finally块分开,这样可以提高代码的清晰度

 1try {
 2   try {
 3      //可能抛出IOException的语句
 4    }
 finally {
 5    is.close();
 6 }

 7}
 catch(IOExceotion e) {
 8   
 9}

10

这样的另外一个好处是,可以catch到finally子句中抛出的异常。这也就引发了另外一个问题,如果在try和finally中都抛出了异常,而且是不同类型的,那么最后返回的是那一个呢?答案是finally中抛出的异常会覆盖try中抛出的异常。从而丢失了try当中抛出的异常信息,让抛出该方法的使用者不能跟踪异常信息。所以,在finally中执行的语句最好是不要抛出异常,但是不幸的是我们有时候不得不在finally中执行一些清楚操作如:关闭输入流InputStream,但是InputStream类的设计者并没有这么设计(将会抛出异常)。

由于finally子句总是会执行,所以在finally中包含return值时,是很危险的。假设我们利用return语句从try中返回,在方法返回之前finally子句的内容将会被执行。如果finally子句当中也包含一个return 语句,那么这个return语句所返回的值,将会覆盖原先return的值。

1public int f(int n) {
2  try {
3      return n*n;
4    }
 finally {
5     if(n==2)
6       return 2;
7  }

8}

在这里如果调用i=f(2);那么i的值将会是2而不是期望的2*2=4


最后最重要的一点,关于一个方法是捕获一个异常还是抛出给调用他的方法
有一点规则   
                                早抛出,晚捕获,尽量把异常抛出给调用它的函数

posted on 2008-02-26 14:05 晓宇 阅读(519) 评论(0)  编辑  收藏 所属分类: JAVA基础


只有注册用户登录后才能发表评论。


网站导航: