java---7异常处理

来源:互联网 发布:java程序员职业规划 编辑:程序博客网 时间:2024/06/06 00:09

在java 语言中,程序员可以在程序中定义异常处理段来捕获和处理异常,在异常发生的时候,一个代表该异常的对象会被创建,并在产生这个异常的方法中被引发。同时这个方法可以选择自己处理异常,也可以抛出异常给别的方法处理。无论怎样该异常都将被捕获并做出相应的处理,这样可以保证程序在出现异常的情况下,仍然可以继续的执行,而不会影响到其他部分的运转,提高了健壮性。

这里写图片描述
Error 类表示Java运行系统内部错误,以及资源耗尽情况下的错误 不能被抛出

实际程序编写中 程序员主要关注Exception 这个异常类 Exception这个异常类又包含两个异常体系
IOException及RuntimeException

IOException 异常处理类由于I/O错误导致的程序异常,例如FileNotFoundException异常类表明用户正在打开的文件不存在 属于I/O异常

RuntimeException 异常主要检查程序员编写的程序中有没有出现除数为0的算术异常、数组越界、数据格式错误等一系列异常。

如:

ArithmeticException 算术异常  java.lang.ArithmeticException: / by zero   除数为0ArrayIndexOutOfBoundsException 数组索引越界异常IllegalArgumentException 非法数据异常(无法通过一个标识或基本的扩展转换将指定的值转换为基础数组的指定类型)NumberFormatException 数字格式异常例如:如果将字符串“123a”映射到到一个整数,您将在服务器日志中看到 NumberFormatException。

在熟悉了异常概念分类以后,将介绍如何捕获异常,Java中提功了try…catch代码段用来捕获可能出现的异常。try的意思就是看其代码段内部的代码是否会出现异常 try 就是检查是否出现异常, catch则是当try中的代码段出现异常后,捕获异常,并做相应的处理
如:

try {           System.out.println(3/0);        } catch (ArithmeticException e1) {    System.out.println("算术异常:除数不能为0");}

需要注意的是try中可能会出现多种异常,则可以在try语句的后面使用多个catch 但是需要注意的是catch捕获异常是按照顺序的如果前一个异常类型被捕获,后面的异常类即使发生也不会被再捕获了,因此一般的习惯是 将最细化的异常类也就是子类先 catch捕获之后再捕获父类异常 如:

    try {        BufferedReader bff=new BufferedReader(new FileReader("next"));    }catch(FileNotFoundException e2){        System.out.println("文件没找到");        System.out.println(e2.getMessage());    }catch (IOException x) {        System.out.println("这是io异常");    }           

下面来看 如何抛出异常

编写代码的过程中如果不想在这段代码中捕获和处理一个可能出现的异常,那么就将这个异常传递出去,传递给调用它的方法去处理该异常。 这个时候就需要使用throw 和 throws 语句

1 throws 语句在方法声明中使用,抛出异常。 public static  void  throwTest() throws ArithmeticException{    //方法中输出3/0会出现异常    System.out.println(3/0);}又或者定义的接口方法声明后public static  void  throwTest() throws ArithmeticException;2 throw 语句在方法体内部使用,抛出异常。

例子:

public class Exception1 {public static  void  throwTest() throws ArithmeticException{    //方法中输出3/0会出现异常    System.out.println(3/0);}public static void File () throws FileNotFoundException{    //由于文件不存在所以会出现异常 文件未找到    BufferedReader bu=new BufferedReader(new FileReader("text.text"));  }public static void FindFile() throws FileNotFoundException{    throw new FileNotFoundException("text.text");}public static void main(String[] args) {    try {        Exception1.throwTest();    } catch (ArithmeticException e) {        System.out.println(e.getMessage());        System.out.println("算术异常");    }    try {        Exception1.File();    } catch (FileNotFoundException e) {        System.out.println(e.getMessage());        e.printStackTrace();    }        try {            Exception1.FindFile();        } catch (FileNotFoundException e) {            System.out.println(e.getMessage());            e.printStackTrace();        }}

自定义异常

前面说到了利用系统提功的标准异常类来捕获和处理异常,如果出现的异常在标准的异常类中没有被定义,则需要建立自己的异常类。建立自己的异常类,要做的知识根据需要 从Exception类或者是从Exception的子类中继承出 需要的类, 习惯上 会经常为每一个异常类,提功一个默认的和一个包含详细信息的构造器, 需要注意的是,自定义异常类 必须由程序员使用 throw 抛出

public class Exception_Diy extends Exception{    public Exception_Diy(){        super("The is myException");    }    public Exception_Diy(String str)    //自定义异常处理类详细信息构造方法;    {        super(str);//调用父类构造方法 初始化    }}public class ExceTest {    public static void main(String[] args) {        String a="嘎嘎嘎";        try {        if(a=="哈哈哈"){ //判断字符串是否相等时 最好不要用 ==            throw new Exception_Diy();//若a不等于哈哈哈则抛出自定义异常                }        } catch (Exception_Diy e) {            // TODO Auto-generated catch block            System.out.println("出问题了");            e.printStackTrace();        }    }}

使用finally 语句段

在之前使用 try …catch语句结构的时候 ,若try 语句中的某一句出现异常情况,那么这部分的try 语句段中,从出现异常的语句开始,之后的所有语句都不会被执行,直到这部分try 语句段结束。

在很多情况下无论是否出现异常,某些语句段都需要被执行,特别是释放资源的操作,如打开文件后的关闭操作,那么就可以把这部分代码放在finally语句段中,即使try 或catch语句段中含有 rturn 语句,程序都会在异常抛出后先执行finally语句段,除非try或catch语句段中执行System.exit()方法,或者是出现Error错误,finally语句段才不会被执行而退出程序。

try...catch..finallytry{可能会出现异常的代码}catch{异常处理代码段 }finally{总是执行的代码段}public class ExceTest {    public static void main(String[] args) {        String a="嘎嘎嘎";         try {        if(a=="哈哈哈"){//判断字符串是否相等时最好不要用 ==            throw new Exception_Diy();//若a不等于哈哈哈则抛出自定义异常                }        } catch (Exception_Diy e) {            // TODO Auto-generated catch block            System.out.println("出问题了");            e.printStackTrace();        }finally{            System.out.println("出问题也得给我执行");        }    }}

另:
super出现在继承了父类的子类中。有三种存在方式:
第一种
super.xxx;(xxx为变量名或对象名)
这种方法意义为,获取父类中的名字为xxx的变量或方法引用。
使用这种方法可以直接访问父类中的变量或对象,进行修改赋值等操作
第二种
super.xxx();(xxx为方法名)
这种方法意义为,直接访问并调用父类中的方法。
第三种
super();
这种方法意义为,调用父类的初始化方法,其实就是调用父类中的public xxx()方法

比如说,你自己从新封装了jdk里面的HashMap类
public class MyMap extends HashMap
这时候,如果你想在实际应用中使用自己的类代替系统中原有的HashMap,就需要写如下代码
public MyMap(){
super();
}
这样,你自己写的类 MyMap map = new MyMap();才能使用
这样做的好处是,你可以不知道原来父类的初始化构造函数是怎么写的。
但是却可以轻易封装它。

 super()在第一行的原因就是: 子类有可能访问了父类对象, 比如在构造函数中使用父类对象的成员函数和变量, 在成员初始化使用了父类, 在代码块中使用了父类等, 所以为保证在子类可以访问父类对象之前要完成对父类对象的初始化

 this()在第一行的原因就是: 为保证父类对象初始化的唯一性. 我们假设一种情况, 类B是类A的子类, 如果this()可以在构造函数的任意行使用, 那么会出现什么情况呢? 首先程序运行到构造函数B()的第一行, 发现没有调用this()和super(), 就自动在第一行补齐了super() , 完成了对父类对象的初始化, 然后返回子类的构造函数继续执行, 当运行到构造函数B()的”this(2) ;”时, 调用B类对象的B(int) 构造函数, 在B(int)中, 还会对父类对象再次初始化! 这就造成了对资源的浪费, 当然也有可能造成某些意想不到的结果, 不管怎样, 总之是不合理的, 所以this() 不能出现在除第一行以外的其他行!