java异常处理

1.异常基础
(1)异常分类
Throwable 类是 Java 语言中所有错误或异常的超类(这就是一切皆可抛的东西)。它有两个子类:Error和Exception。
Error类体系描述了Java运行系统中的内部错误以及资源耗尽的情形。应用程序不应该抛出这种类型的对象(一般是由虚拟机抛出)。如果出现这种错误,除了尽力使程序安全
退出外,在其他方面是无能为力的。所以,在进行程序设计时,应该更关注Exception体系
Exception:它指出了合理的应用程序想要捕获的条件。Exception又分为两类:一种是CheckedException,一种是UncheckedException。
这两种Exception的区别主要是CheckedException需要用try...catch...显示的捕获,而UncheckedException不需要捕获。通常
UncheckedException又叫做RuntimeException。对于可恢复的条件使用被检查的异常(CheckedException),对于程序错误(言外之意不
可恢复,大错已经酿成)使用运行时异常(RuntimeException)。
RuntimeException:RuntimeException体系包括错误的类型转换、数组越界访问和试图访问空指针等等。
其他非RuntimeException(IOException等等):这类异常一般是外部错误,例如试图从文件尾后读取数据等,这并不是程序本身的错误,而是在应用环境中出现的外部错误。
在编写程序过程中try...catch...捕捉的异常都是CheckedException。io包中的IOException及其子类,这些都是CheckedException。
1. java.lang.NullPointerException
  "程序遇上了空指针",就是调用了未经初始化的对象或者是不具有的对象。
2.java.lang.ArithmeticException
  "数学运算异常",比如程序中出现了除以零这样的运算就会出这样的异常,对这种异常,大家就要好好检查一下本人程序中涉及到数学运算的地方,公式是不是有不妥了。
3.java.lang.ArrayIndexOutOfBoundsException
  "数组下标越界".
4.java.lang.IllegalAccessException
  这个异常的注释是"没有访问权限",当应用程序要调用一个类,但当前的方法即没有对该类的访问权限便会出现这个异常。对程序中用了package的情况下要注意这个异常。
try...catch...是一种"事务性"的保障,它的目的是保证程序在异常的情况下运行完毕,同时它还会告知程序员程序中出错的详细信息。
下面是这几个类的层次图:
 java.lang.Object
    java.lang.Throwable
     java.lang.Exception
       java.lang.RuntimeException
         java.lang.Error
          java.lang.ThreadDeath
(2)异常的例子
第一个例子:
public class Calculator {
    public int devide(int num1, int num2) {
        //判断除数是否为0
        if(num2 == 0) {
            throw new IllegalArgumentException("除数不能为零");
        }         
        return num1/num2;
    }
}
第二个例子:
/*利用关键字throws进行异常处理*/
public class ExceptionTest1 {
 public static int divide(int iNum1, int iNum2) throws ArithmeticException {
   return iNum1 / iNum2;
 }
 public static void main(String[] args) {
  try {
    int iNum = divide(5,0);
    System.out.println(iNum);
  } catch (ArithmeticException e) {
    e.printStackTrace();//指出异常的类型、性质、栈层次及出现程序中的位置
  }
 }
}
 异常对象中包含的信息 :一般情况下,异常对象唯一有用的信息就是类型信息。但使用异常带字符串的构造函数时,这个字符串还可以作为额外的信息。调用异常对象的
 getMessage()、toString()或者printStackTrace()方法可以分别得到异常对象的额外信息、类名和调用堆栈的信息。并且后一种包含的信息是前一种的超集。
 catch语句可以有多个,用来匹配多个异常,匹配上多个中一个后,执行catch语句块时候仅仅执行匹配上的异常。catch的类型是Java语言中定义的或者程序员自己定义的,表示代码抛
出异常的类型,异常的变量名表示抛出异常的对象的引用,如果catch捕获并匹配上了该异常,那么就可以直接用这个异常变量名,此时该异常变量名指向所匹配的异常,并且在catch代
码块中可以直接引用。
(3)重新抛出异常
重新抛出异常对你来说可能是一个很好的解脱。原封不动的把这个异常抛给上一级,抛给调用这个方法的人,让他来费脑筋吧:
public static void readFile(String file) throws FileNotFoundException {
    try {
        BufferedInputStream in = new BufferedInputStream(new FileInputStream(file));
    } catch (FileNotFoundException e) {
        e.printStackTrace();
        System.err.println("不知道如何处理该异常或者根本不想处理它,但是不做处理又不合适,这是重新抛出异常交给上一级处理");
        //重新抛出异常
        throw e;
    }
}
(4)异常链
Throwable 包含了其线程创建时线程执行堆栈的快照。它还包含了给出有关错误更多信息的消息字符串,可以包含 cause(原因):另一个导致此 throwable 抛出的 throwable。
它也称为异常链设施,因为 cause 自身也会有 cause,依此类推,就形成了异常链,每个异常都是由另一个异常引起的。
异常链就是把原始的异常包装为新的异常类,并在新的异常类中封装了原始异常类,这样做的目的在于找到异常的根本原因。
通过Throwable的两个构造方法可以创建自定义的包含异常原因的异常类型:
Throwable(String message, Throwable cause)
构造一个带指定详细消息和 cause 的新 throwable。

Throwable(Throwable cause)
构造一个带指定 cause 和 (cause==null ? null :cause.toString())(它通常包含类和 cause 的详细消息)的详细消息的新 throwable。

getCause()
返回此 throwable 的 cause;如果 cause 不存在或未知,则返回 null。

initCause(Throwable cause)
将此 throwable 的 cause 初始化为指定值。

在Throwable的子类Exception中,也有类似的指定异常原因的构造方法:
Exception(String message, Throwable cause)
构造带指定详细消息和原因的新异常。

Exception(Throwable cause)
根据指定的原因和 (cause==null ? null : cause.toString()) 的详细消息构造新异常(它通常包含 cause 的类和详细消息)。

因此,可以通过扩展Exception类来构造带有异常原因的新的异常类。
异常链的特性是所有异常均具备的,因为这个initCause()方法是从Throwable继承的。
public class NeverCaught {
    static void f() throws ExceptionB{
        throw new ExceptionB("exception b");
    }
    static void g() throws ExceptionC {
        try {
            f();
        } catch (ExceptionB e) {
            ExceptionC c = new ExceptionC("exception a");
            //异常连
            c.initCause(e);
            throw c;
        }
    }
    public static void main(String[] args) {
            try {
                g();
            } catch (ExceptionC e) {
                e.printStackTrace();
            }
    }
}
(5)finally
Try...finally结构也是保证资源正确关闭的一个手段。如果你不清楚代码执行过程中会发生什么异
常情况会导致资源不能得到清理,那么你就用try对这段"可疑"代码进行包装,然后在finally中进行
资源的清理。
public void readFile(String file) {
        BufferedReader reader = null;
        try {
            reader = new BufferedReader(new InputStreamReader(
                    new FileInputStream(file)));
            // do some other work
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } finally {
            try {
                reader.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
(6)自定义异常类
创建Exception或者RuntimeException的子类即可得到一个自定义的异常类。例如:
public class MyException extends Exception{
 public MyException(){}
 public MyException(String smg){
 super(smg);
 }
}
使用自定义的异常
用throws声明方法可能抛出自定义的异常,并用throw语句在适当的地方抛出自定义的异常。例如:
在某种条件抛出异常
void test1() throws MyException{
if(....){
 throw new MyException();
 }
}
将异常转型(也叫转译),使得异常更易读易于理解
  public void test2() throws MyException{
  ...
  try{
  ...
  }catch(SQLException e){
  ...
  throw new MyException();
  }
  }
  还有一个代码,很有意思:
public void test2() throws MyException{
  ...
  try {
  ...
  } catch (MyException e) {
  throw e;
  }
  }
  这段代码实际上捕获了异常,然后又和盘托出,没有一点意义,如果这样还有什么好处理的,不处理就行了,
直接在方法前用throws声明抛出不就得了。异常的捕获就要做一些有意义的处理。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值