2017.4.7 java异常处理总结
目录
1.java异常处理的几种错误做法
2.异常处理示例
3.常用异常
4.异常类的继承关系
5.异常处理机制
6.Throw和Throws的区别
7.e.toString(), e.getCause() , e.getMeage(), e.printStackTrace()
1.java异常处理的几种错误做法
http://blog.csdn.net/msyqmsyq/article/details/51504570
(1)捕捉异常却不处理
注意:调用一下printStackTrace算不上“处理异常”。因为调试阶段结束后,printStackTrace就不会再在异常处理模块负重要责任了。
1 catch(Exception ex) { 2 ex.printStackTrace(); 3 }
(2)不指定具体的异常,全部用Exception
在catch语句中尽可能指定具体的异常类型,必要时使用多个catch。最后再使用Exception。
1 try{ 2 //可能发生异常的代码块 3 }catch(异常类名 e1){ 4 //处理代码 5 } 6 catch(异常类 e2){ 7 //处理代码 8 }
在JSE7中引入了新的语法:这样在该catch代码块中就用能够接受所有的在括号内部的异常类型的对象了。
1 catch(异常类名 e1 | 异常类名 e2 | 异常类名e3 | ………)
(3)占据资源不释放
充分使用finally关键字,执行清理任务的代码。
(4)不提供异常的详细信息
printStackTrace的堆栈跟踪功能显示出程序运行到当前类的执行流程,但只提供了一些最基本的信息,未能说明实际导致错误的原因,同时也不易解读。因此,在出现异常时,最好能够提供一些文字信息,例如当前正在执行的类、方法和其他状态信息,包括以一种更适合阅读的方式整理和组织printStackTrace提供的信息。
(5)try/catch 块太庞大
把所有代码而不是可能出现异常的代码,都放入异常处理模块。原因是,不愿意去分析一大块代码中,哪几行可能会出现哪几种异常,因此就容易漏判。
(6)输出数据不完整
如果代码中间抛出了异常,前面执行的代码会不会有影响,后面输出的数据要不要做处理,都是要考虑的。对有些系统来说,数据不完整可能比系统停止带来的损失更大。
比如可以这样处理:在for循环输出数据时,抛出了异常。可以向输出设备写一些信息,声明数据的不完整性;另一种可能有效的办法是,先缓冲要输出的数据,准备好全部数据之后再一次性输出。
在JavaSE7中已经给出了带资源的try语句用来完成和finally相似的功能,即在try关键字后面带上参数。那么在try块中使用完这个文件流时,就不用使用finally块来将文件流关闭了,程序会自动的将这个文件流关闭,确保文件不被损坏,这样就提供了更加简单的方法来清理资源。
1 try(InputSTream fis = new FileInputStream (source)){ 2 //可能发生异常的代码 3 }catch{ 4 //处理代码 5 }
2.异常处理示例
错误示例:
1 OutputStreamWriter out = ... 2 java.sql.Connection conn = ... 3 try { 4 Statement stat = conn.createStatement(); 5 ResultSet rs = stat.executeQuery("select uid, name from user"); 7 while (rs.next()) 8 { 9 out.println("ID:" + rs.getString("uid")",姓名:" + rs.getString("name")); 11 } 12 conn.close(); 13 out.close(); 14 } 15 catch(Exception ex) { 17 ex.printStackTrace(); 18 }
按照上面的原则修改后:
1 OutputStreamWriter out = ... 2 java.sql.Connection conn = ... 3 try { 4 Statement stat = conn.createStatement(); 5 ResultSet rs = stat.executeQuery("select uid, name from user"); 7 while (rs.next()){ 9 out.println("ID:" + rs.getString("uid") + ",姓名: " + rs.getString("name")); 10 } 11 } 12 catch(SQLException sqlex){//指定具体的异常14 out.println("警告:数据不完整"); 15 throw new ApplicationException("读取数据时出现SQL错误", sqlex); //处理异常或抛出新异常 16 } 17 catch(IOException ioex){//指定具体的异常 19 throw new ApplicationException("写入数据时出现IO错误", ioex); //处理异常或抛出新异常 20 } 21 finally{ //释放资源 23 if (conn != null) { 24 try { 25 conn.close(); 26 } 27 catch(SQLException sqlex2){ //异常导致中断后,做的处理 29 System.err(this.getClass().getName() + ".mymethod - 不能关闭数据库连接: " + sqlex2.toString()); 30 } 31 } 32 33 if (out != null) { 34 try { 35 out.close(); 36 } 37 catch(IOException ioex2){ //异常导致中断后,做的处理 39 System.err(this.getClass().getName() + ".mymethod - 不能关闭输出文件" + ioex2.toString()); 40 } 41 } 42 }
3.常用异常
空指针异常 | NullPointerExption | 类型强制转换异常 | ClassCastException |
数组负下标异常 | NegativeArrayException | 数组下标越界异常 | ArrayIndexOutOfBoundsException |
文件未找到异常 | FileNotFoundException | 输入输出异常 | IOException |
字符串转换为数字异常 | NumberFormatException | NumberFormatException | SQLException |
运行时异常 | RuntimeException | 解析JSON异常 | JSONException |
UnknownSessionException | ExpiredSessionException | ||
插入重复数据异常 |
DuplicateKeyException
|
文件已结束异常 | EOFException |
4.异常类的继承关系
http://blog.csdn.net/hguisu/article/details/6155636
注意:异常分为受检类型和非受检类型。
1 受检类型:继承了Exception但是不继承RuntimeException的子类。
在程序编译期间就会检查,如果发现存在受检异常,那么程序根本就不能执行。不论是用catch还是用throws抛向上一级的catch,该异常必须进行处理。 2 非受检类型:Error,和继承RuntimeException的子类。
在执行期间才会发现异常并中断,在编译阶段不会检查。
比如下面这段代码中,存在两个异常,IOException(受检)和NumberFormatException(非受检)。
1 去掉IOException,无法通过编译。但是去掉NumberFormatException,可以通过编译。 2 执行时,如果str无法转换成int,也还是会抛出异常。如果没有catch或者抛向上级的catch,运行阶段(非调试阶段)会造成无提示无处理的程序中断。
1 public void read() throws IOException, NumberFormatException{ 2 String str; 3 while(str==reader.readLine()!=null){ 4 int n = Integer.parseInt(str); 5 System.out.println(n); 6 } 7 }
5.异常处理机制
两种方式:catch并处理,或者抛向上级的catch。这里重点讲解抛向上级的catch。
当方法抛出异常列表的异常时,方法将不对这些类型及其子类类型的异常作处理,而抛向调用该方法的方法,由他去处理。
1 import java.lang.Exception; 2 public class TestException { 3 static void pop() throws NegativeArraySizeException { 4 // 定义方法并抛出NegativeArraySizeException异常 5 int[] arr = new int[-3]; // 创建数组 6 } 7 8 public static void main(String[] args) { // 主方法 9 try { // try语句处理异常信息 10 pop(); // 调用pop()方法 11 } catch (NegativeArraySizeException e) { 12 System.out.println("pop()方法抛出的异常");// 输出异常信息 13 } 14 } 15 16 }
6.Throw和Throws的区别
1 throw出现在方法内部,用于抛出异常。 2 throws出现在方法上,用于声明异常。
3 如果通过throw抛出了异常(2),并且这个异常是检查异常,则方法名上也必须用throws来声明方法可能会这个异常(1)。 4 程序会在throw语句后立即终止,它后面的语句执行不到,然后在包含它的所有try块中(可能在上层调用函数中)从里向外寻找含有与其匹配的catch子句的try块(3)。
1 package Test; 2 import java.lang.Exception; 3 public class TestException { 4 static int quotient(int x, int y) throws MyException { // 定义方法抛出异常 (1) 5 if (y < 0) { // 判断参数是否小于0 6 throw new MyException("除数不能是负数"); // 异常信息 (2) 7 } 8 return x/y; // 返回值 9 } 10 public static void main(String args[]) { // 主方法 11 int a =3; 12 int b =0; 13 try { // try语句包含可能发生异常的语句 14 int result = quotient(a, b); // 调用方法quotient() 15 } catch (MyException e) { // 处理自定义异常 (3) 16 System.out.println(e.getMessage()); // 输出异常信息 17 } catch (ArithmeticException e) { // 处理ArithmeticException异常 18 System.out.println("除数不能为0"); // 输出提示信息 19 } catch (Exception e) { // 处理其他异常 20 System.out.println("程序发生了其他的异常"); // 输出提示信息 21 } 22 } 23 24 } 25 class MyException extends Exception { // 创建自定义异常类 26 String message; // 定义String类型变量 27 public MyException(String ErrorMessagr) { // 父类方法 28 message = ErrorMessagr; 29 } 30 31 public String getMessage() { // 覆盖getMessage()方法 32 return message; 33 } 34 }
7. e.toString(), e.getCause() , e.getMeage(), e.printStackTrace()
2017.4.7 e.toString() 与 e.getMessage()的区别
1 e.toString() : 异常的类型及信息,比如java.lang.ArithmeticException: / by zero 2 e.getMessage() : 异常的信息, 比如/ by zero 3 e.getCause() : 异常的原因,如果cause不存在或未知,返回null。 4 e.printStackTrace() : 异常的跟踪栈。在运行阶段(非调试阶段)没有帮助。