【原】Java学习笔记030 - 异常
1 package cn.temptation; 2 3 public class Sample01 { 4 public static void main(String[] args) { 5 /* 6 * 异常:Java程序在运行过程中出现的错误 7 * 8 * 类 Throwable:Java 语言中所有错误或异常的超类。 9 * 只有当对象是此类(或其子类之一)的实例时,才能通过 Java 虚拟机或者 Java throw 语句抛出。 10 * 类似地,只有此类或其子类之一才可以是 catch 子句中的参数类型。 11 * 12 * 类 Error:Error 是 Throwable 的子类,用于指示合理的应用程序不应该试图捕获的严重问题。 13 * 大多数这样的错误都是异常条件。虽然 ThreadDeath 错误是一个“正规”的条件,但它也是 Error 的子类,因为大多数应用程序都不应该试图捕获它。 14 * 15 * 类 Exception:Exception 类及其子类是 Throwable 的一种形式,它指出了合理的应用程序想要捕获的条件。 16 * 17 * 异常的分类: 18 * 1、编译时异常:Exception类中除去RuntimeException及其子类以外其他的 19 * 2、运行时异常:RuntimeException及其子类 20 * 21 * 异常的处理方式: 22 * 1、try...catch...finally格式及其变体 23 * 2、throws/throw 24 * 25 * try...catch...finally处理方式: 26 * try { 27 * 可能出现问题的代码 28 * } catch(异常名称 变量) { 29 * 针对问题的处理 30 * } finally { 31 * 释放资源等操作 32 * } 33 * 34 * try...catch...finally处理的变体方式: 35 * try { 36 * 可能出现问题的代码 37 * } catch(异常名称 变量) { 38 * 针对问题的处理 39 * } 40 */ 41 42 // 下句语句编译阶段无语法错误,但是执行时产生异常,这个异常不是由开发人员来处理,应该由开发人员编写代码时就进行判断处理 43 // System.out.println(2 / 0); 44 45 // 【针对单个异常】 46 // try { 47 // System.out.println(2 / 0); 48 // } catch (ArithmeticException e) { 49 // System.out.println("除数不能为0"); 50 // } 51 52 // 【针对多个异常】 53 int[] arr = { 1, 2, 3 }; 54 55 // try { 56 // // 如果没有进行异常处理,执行时,首先JVM捕获数组越界异常 57 // System.out.println(arr[3]); 58 // System.out.println(2 / 0); 59 // } catch (ArrayIndexOutOfBoundsException e) { 60 // System.out.println("数组的索引越界"); 61 // } catch (ArithmeticException e) { 62 // System.out.println("除数不能为0"); 63 // } 64 65 // 上述的异常处理代码会显示"数组的索引越界",因为代码的顺序执行,首先捕获到索引越界异常,如果解决掉这个问题,再执行会捕获到除数为0的异常 66 67 // try { 68 // System.out.println(arr[3]); 69 // System.out.println(2 / 0); 70 // } catch (Exception e) { 71 // System.out.println("代码有问题"); 72 // } 73 74 // 上述的异常处理代码使用异常基类Exception类,这样不用明确指出是哪一种异常(偷懒写法) 75 76 // 【JDK 1.7之后开始支持的语法】 77 try { 78 System.out.println(arr[3]); 79 System.out.println(2 / 0); 80 } catch (ArrayIndexOutOfBoundsException | ArithmeticException e) { 81 System.out.println("代码有问题"); 82 } 83 84 // 上述的异常处理代码需要多个异常是针对同一类类型的问题,否则无法明确具体是什么异常 85 } 86 }
1 package cn.temptation; 2 3 public class Sample02 { 4 public static void main(String[] args) { 5 /* 6 * 对异常的两种处理方式的理解: 7 * 类比生病 8 * 1、哪里有病了哪里疼痛,直接就在对应的问题就发现问题 9 * 2、有病的地方并不是病因产生的地方,而是病状呈现的地方,也就是问题不断抛出最后得到的结果 10 */ 11 12 // try...catch...finally处理时的注意问题: 13 // 1、同时使用父类异常 和 子类异常时,父类异常不能写在子类异常之前,否则有语法错误 14 // try { 15 // System.out.println(2 / 0); 16 // } catch (Exception e) { 17 // System.out.println("代码有问题"); 18 // } catch (ArithmeticException e) { 19 // // 语法错误:Unreachable catch block for ArithmeticException. It is already handled by the catch block for Exception 20 // System.out.println("除数不能为0"); 21 // } 22 23 // 下面语句执行时显示子类异常信息 24 try { 25 System.out.println(2 / 0); 26 } catch (ArithmeticException e) { 27 // 语法错误:Unreachable catch block for ArithmeticException. It is already handled by the catch block for Exception 28 System.out.println("除数不能为0"); 29 } catch (Exception e) { 30 System.out.println("代码有问题"); 31 } 32 } 33 }
1 package cn.temptation; 2 3 public class Sample03 { 4 public static void main(String[] args) { 5 /* 6 * Throwable类的常用成员方法: 7 * 1、String getMessage() :返回此 throwable 的详细消息字符串。 8 * 2、String toString() :返回此 throwable 的简短描述。 9 * 3、void printStackTrace() :将此 throwable 及其追踪输出至标准错误流。 10 */ 11 12 try { 13 System.out.println(2 / 0); 14 } catch (Exception e) { 15 System.out.println(e.getMessage()); // / by zero 16 System.out.println(e.toString()); // java.lang.ArithmeticException: / by zero 17 e.printStackTrace(); // java.lang.ArithmeticException: / by zero at cn.temptation.Sample03.main(Sample03.java:13) 18 } 19 } 20 }
1 package cn.temptation; 2 3 public class Sample04 { 4 public static void main(String[] args) { 5 /* 6 * throws 关键字的使用: 7 * 定义方法时,使用throws关键字标记需要暴露出来被开发人员处理的问题 8 */ 9 10 // 下句语句对calc方法的调用,因为在主函数中没有对calc方法抛出的异常进行处理,所以异常还是由jvm进行捕获 11 // 调用calc方法,收到其抛出的异常,没有进行处理 12 // calc(); 13 14 try { 15 // 调用calc方法,收到其抛出的异常,并进行处理 16 calc(); 17 } catch (ArithmeticException e) { 18 System.out.println("除数不为0"); 19 } 20 } 21 22 // 在方法内部对异常不进行处理,在方法的声明上通过throws标记需要处理的异常,并向外抛出 23 // 定义计算方法 24 public static void calc() throws ArithmeticException { 25 System.out.println(2 / 0); 26 } 27 }
1 package cn.temptation; 2 3 public class Sample05 { 4 public static void main(String[] args) { 5 /* 6 * throw关键字的使用: 7 * 用在方法内部,出现某种情况程序无法继续运行时,需要进行跳转通过throw把异常对象进行抛出 8 * 9 * 10 * throws 和 throw 的区别: 11 * 1、throws 12 * A:用在方法声明中,后面是异常类名 13 * B:throws后可以有多个异常类名,之间使用英文逗号分隔 14 * C:表示抛出异常,由方法的调用者进行处理 15 * D:throws表示出现异常的可能,不一定会发生这些异常 16 * 17 * 2、throw 18 * A:用在方法内,后面是异常类的对象 19 * B:throw后只能抛出一个异常对象 20 * C:表示抛出异常,由方法内的语句处理,方法被调用时,调用方法处进行捕获处理 21 * D:throw表示抛出异常,执行throw一定是抛出了某种异常 22 */ 23 24 // 使用throw关键字,在方法中抛出异常的实例对象,方法调用时没有语法错误 25 // calc(); 26 27 // 下面代码捕获到ArithmeticException异常,并执行catch代码块的处理 28 // try { 29 // calc(); 30 // } catch (ArithmeticException e) { 31 // System.out.println("计算异常"); 32 // } 33 34 // 方法声明上throws出的异常 和 方法内throw出的异常是父子关系,必须进行异常处理,否则就语法出错 35 // method1(); 36 37 // try { 38 // method1(); 39 // } catch (Exception e) { 40 // System.out.println("除数不为0"); 41 // } 42 43 // 方法声明上throws出的异常 和 方法内throw出的异常同级且不相同,以throw出的异常为准 44 method2(); 45 } 46 47 // 声明计算方法 48 public static void calc() { 49 int i = 2; 50 int j = 0; 51 52 if (j == 0) { // 判断除数是0 53 throw new ArithmeticException(); 54 } else { 55 System.out.println(i / j); 56 } 57 } 58 59 public static void method1() throws Exception { 60 int i = 2; 61 int j = 0; 62 63 if (j == 0) { // 判断除数是0 64 throw new ArithmeticException(); 65 } else { 66 System.out.println(i / j); 67 } 68 } 69 70 public static void method2() throws ArrayIndexOutOfBoundsException { 71 int i = 2; 72 int j = 0; 73 74 if (j == 0) { // 判断除数是0 75 throw new ArithmeticException(); 76 } else { 77 System.out.println(i / j); 78 } 79 } 80 }
1 package cn.temptation; 2 3 public class Sample06 { 4 public static void main(String[] args) { 5 /* 6 * 两种异常处理方式的选择: 7 * 1、如果在方法内部进行处理,选择try...catch...finally结构 8 * 2、如果在方法外部进行处理,选择throws/throw 9 * 10 * finally的特点:finally中的语句一定会被执行 11 * 注意:在执行finally语句块之前虚拟机终止了,那么finally语句块中的语句不会执行 12 */ 13 14 try { 15 System.out.println(2 / 0); 16 } catch (Exception e) { 17 System.out.println("异常处理"); 18 /* 19 * System类的常用成员方法: 20 * static void exit(int status) :终止当前正在运行的 Java 虚拟机。 21 */ 22 System.exit(0); 23 } finally { 24 System.out.println("finally中的语句一定会被执行"); 25 } 26 } 27 }
1 package cn.temptation; 2 3 public class Sample07 { 4 public static void main(String[] args) { 5 // 在try...catch...finally...结构中使用return的问题: 6 // 1、catch语句块中有return语句,finally语句块中没有return语句,执行顺序为: 7 // 先执行catch语句块中return语句之前的语句,再执行finally语句块中的语句,最后执行catch中的return语句,显示结果为4 8 // 2、catch语句块中有return语句,finally语句块中也有return语句,执行顺序为: 9 // 先执行catch语句块中return语句之前的语句,再执行catch中的return语句,然后执行finally语句块中的语句,最后执行finally语句块中的return语句,显示结果为5 10 System.out.println(show()); 11 } 12 13 public static int show() { 14 try { 15 System.out.println(2 / 0); 16 return 3; 17 } catch (Exception e) { 18 System.out.println("异常处理"); 19 return 4; 20 } finally { 21 System.out.println("finally中的语句"); 22 return 5; 23 } 24 } 25 }
1 package cn.temptation; 2 3 public class Sample08 { 4 public static void main(String[] args) { 5 // try...catch...finally...形式 6 // 完整形式 7 try { 8 9 } catch (Exception e) { 10 11 } finally { 12 13 } 14 15 // try...catch..(单个异常) 16 try { 17 18 } catch (Exception e) { 19 20 } 21 22 // try...catch..(多个异常) 23 try { 24 25 } catch (ArithmeticException e) { 26 27 } catch (Exception e) { 28 29 } 30 31 // try...finally... 32 // 没有catch代码块结构语法也正确,这种形式目的是为了使用后释放资源 33 try { 34 35 } finally { 36 37 } 38 39 // 语法错误 40 // try { 41 // 42 // } 43 44 // 语法错误 45 // catch (Exception e) { 46 // 47 // } 48 49 // 语法错误 50 // catch (Exception e) { 51 // 52 // } finally { 53 // 54 // } 55 56 // 语法错误 57 // finally { 58 // 59 // } 60 } 61 }
1 package cn.temptation; 2 3 public class Sample09 { 4 public static void main(String[] args) { 5 // 自定义异常类 6 try { 7 show(200); 8 } catch (TestException e) { 9 e.printStackTrace(); 10 } 11 } 12 13 public static void show(int age) throws TestException { 14 if (age < 0 || age > 150) { 15 throw new TestException("年龄错误!"); 16 } else { 17 System.out.println("年龄为:" + age); 18 } 19 } 20 } 21 22 /** 23 * 自定义异常类 24 */ 25 class TestException extends Exception { 26 // 构造函数 27 public TestException() { 28 29 } 30 31 public TestException(String msg) { 32 super(msg); 33 } 34 }