/* java 中的所有异常类都是继承自 Throwable类,就是说所有的异常类都是 Throwable类的子类. 所有的类都是 Object 类的子类,Throwable类有两个子类,Error类和Exception类, 主要关注的就是 Exception类, 其中 Exception 类包括 RuntimeException和其他异常类 */ public class Hi { public static void exception() { int i[] = {1,2,3}; System.out.println("i[3] = "+i[3]); } public static void main(String[] args) { exception(); // 数组越界异常,报错 } } // 常见的运行时异常类(RuntimeException) java.lang.ArithmeticException: 算术异常 java.lang.ArrayIndexOutOfBoundsException:数组越界异常 java.lang.ArrayStoreException:数组元素值类型与数组类型不符异常 java.lang.ClassCastException:对象转换异常 java.lang.IllegalArgumentException:调用方法时传入非法参数异常 java.lang.IllegalMonitorStateException:非法监控操作异常 java.lang.IllegalStateException:java环境或java应用程序状态异常 java.lang.IllegalThreadStateException:线程没有处于请求操作所要求状态异常 java.lang.IndexOutOfBoundsException:索引越界异常 java.lang.NegativeArraySizeException:数组长度为负值异常 java.lang.NullPointerException:空指向异常 java.lang.NumberFormatException:数字格式异常 java.lang.SecurityException:违反安全性异常 java.lang.StringIndexOutOfBoundsException:字符串索引越界异常 java.lang.UnsupportedOperationException:操作错误异常 检查异常 java.lang.Exception:处理异常的基本异常类 java.lang.ClassNotFoundException:找不到相关异常 java.lang.CloneNotSupportedException:使用继承自Object类的 clone()方法,但是该类没有实现 Cloneable 接口 java.lang.IllegalAccessException:访问类被拒绝异常(与权限有关) java.lang.InstantiationException:创建抽象类或接口对象实例异常 java.lang.InterruptedException:线程被另一个线程中断异常 java.lang.NosuchFieldException:在类中找不到此字段异常 java.lang.NosuchMethodException:在类中找不到此方法异常 /* 虽然系统提供了默认的异常处理程序,但是一般情况下,还是开发人员更希望的是自己处理异常: 两种处理异常处理方法: try ... catch ... finally ...//语句处理异常 throws 关键字将异常传递出来 */ try { // 可能抛出异常的语句 }catch(异常类型1 异常对象名1) { // 对该类型的异常进行处理的语句 }[catch(异常类型2 异常对象名2) {} ... ] [finally{ // 一定会运行的程序代码 }] // =========== public class Hi { public static void main(String[] args) { int i[] = {1,2,3}; try { System.out.println("i[0] = "+i[0]); System.out.println("i[3] = "+i[3]); // 数组越界异常 }catch(ArrayIndexOutOfBoundsException e) { System.out.println("异常信息:"+e); } System.out.println("i[1] = "+i[1]); // 正常执行 } } /* i[0] = 1 异常信息:java.lang.ArrayIndexOutOfBoundsException: 3 i[1] = 2 */ // ============= public class Hi { public static void main(String[] args) { int i[] = {1,2,3}; try { System.out.println("i[0] = "+i[0]); System.out.println("i[3] = "+i[3]); // 数组越界 }catch(ArrayIndexOutOfBoundsException e) { System.out.println("异常信息:"+e); }finally { System.out.println("无论如何都执行的语句"); } System.out.println("i[1] = "+i[1]); // 正常执行 } } /* i[0] = 1 异常信息:java.lang.ArrayIndexOutOfBoundsException: 3 无论如何都执行的语句 i[1] = 2 */ // ============= // 多个 catch语句块 import java.util.Scanner; import java.util.InputMismatchException; public class Hi { public static void main(String[] args) { Scanner read = new Scanner(System.in); int arr[] = new int[5]; try { System.out.println("请输入数组元素:"); for(int i=0; i<arr.length; i++) { arr[i] = read.nextInt(); } System.out.println("请输入数组元素索引:"); int n = read.nextInt(); System.out.println("arr["+n+"]="+arr[n]); int m = arr[3]/arr[0]; System.out.println("m = "+m); }catch(ArrayIndexOutOfBoundsException e) // 捕捉数组越界异常 { System.out.println("异常:"+e); }catch(ArithmeticException e) // 捕捉算术异常 { System.out.println("异常:"+e); }catch(InputMismatchException e) // 捕捉输入不匹配异常 { System.out.println("异常:"+e); } System.out.println("end ... "); } } // ============ throws 使用格式 [访问控制符] 返回类型 方法名称([参数列表]) throws 异常类1[, 异常类2..]{} import java.io.IOException; import java.io.FileInputStream; public class Hi { public static void arrException() throws IOException { FileInputStream f = new FileInputStream("不存在的文档.txt"); } public static void main(String[] args) { try { arrException(); }catch(Exception e) { System.out.println("异常:"+e); } } } // 异常:java.io.FileNotFoundException: 不存在的文档.txt (系统找不到指定的文件。) // ========== import java.io.IOException; import java.io.FileInputStream; public class Hi { public static void arrException() throws IOException { FileInputStream f = new FileInputStream("文件不存在.txt"); } public static void main(String[] args) throws Exception { arrException(); } } /* Exception in thread "main" java. 不到指定的文件。) at java.io.FileInputStre at java.io.FileInputStre at java.io.FileInputStre at Hi.arrException(Hi.ja at Hi.main(Hi.java:11) */ 主方法 main()使用了 throws 关键字, 没有使用 try .. catch 语句,所以arrException()方法 将异常抛出交给 main() 方法时,main也不作任何处理继续向上抛出, 直至抛给 JVM.JVM就会调用默认异常处理程序处理, 即中断程序的执行并退出。 // =============== /** throw 自行抛出异常。throw语句可以单独使用,用于方法体内部, throw 抛出的不是异常类,而是异常类的实例。 如果抛出了检查异常,则还应该在方法头部声明方法可能抛出的异常类型, 该方法的调用者也必须检查处理抛出的异常。 不检测异常与检测异常 不检测异常是指对 Error类或其子类对象和 RuntimeException类或其子类 就不用捕获或抛出。其他的异常类就是检查异常 throw 使用格式 throw 异常对象; */ // 自行抛出不检查异常 import java.io.IOException; public class Hi { public static void arrException() // 不需要指明可能抛出的类型 { throw new NullPointerException("自行抛出不检查异常--空指定异常"); } public static void main(String[] args) { try // 处理异常 { arrException(); // 产生异常 }catch(Exception e) // 捕获异常 { System.out.println(e); } } } /* result: java.lang.NullPointerException: 自行抛出不检查异常--空指定异常 */ import java.io.IOException; public class Hi { public static void arrException() throws Exception { throw new IOException("自行抛出检查异常--IO异常"); } public static void main(String[] args) { try // 处理异常 { arrException(); // 产生异常 }catch(Exception e) // 捕获异常 { System.out.println(e); } } } // java.io.IOException: 自行抛出检查异常--IO异常 /* 以上两个程序产生的异常对象都是手工产生的。使用 throw抛出不检查异常时, 不需要在方法头部声明方法可能抛出的异常类型。 而抛出检查异常时,必须在方法头部声明可能抛出的异常类型, 该方法的调用者也必须检查处理抛出异常. */ // ============== // catch和 throw同时使用 import java.util.Scanner; public class Hi { public static void arrException(int arr[]) { try { int m = arr[2]/arr[0]; System.out.println(arr[2]+"/"+arr[0]+"="+m); }catch(ArithmeticException e) { e.printStackTrace(); /*java.lang.ArithmeticException: / at Hi.arrException(Hi.ja at Hi.main(Hi.java:27) */ throw new ArithmeticException("被除数不能为0,所以arr[0]不能为0"); } } public static void main(String[] args) { Scanner scan = new Scanner(System.in); int arr[] = new int[5]; try { for(int i = 0; i<arr.length; i++) { System.out.println("第"+(i+1)+"元素:"); arr[i] = scan.nextInt(); } arrException(arr); }catch(Exception e) { System.out.println("异常信息:"+e); } } } /* java.lang.ArithmeticException: / by zero at Hi.arrException(Hi.java:8) at Hi.main(Hi.java:31) 异常信息:java.lang.ArithmeticException: 被除数不能为0,所以arr[0]不能为0 */ /** 自定义异常类格式 [public ] class 自定义的异常类名 extends Exception类或Exception类的子类{} */ import java.util.Scanner; class MyNumberException extends Exception // 自定义异常类 { public MyNumberException(){} // 无参构造方法 public MyNumberException(String message) // 参数为 string 类型的构造方法 { super(message); } } public class Hi { public static void main(String[] args) { Scanner scan = new Scanner(System.in); int arr[] = new int[5]; try // 处理异常 { for(int i = 0; i < arr.length; i++) { System.out.println("输入第"+(i+1)+"个数:"); arr[i] = scan.nextInt(); if(arr[i] < 0 || arr[i] > 100) { throw new MyNumberException("你输入的数不在 0 - 100"); } } }catch(MyNumberException e) // 抓取异常 { System.out.println(e); // 输出异常信息 }catch(Exception e) // 抓取异常 { System.out.println(e); // 输出异常信息 } } } /** 当输入的数字不在 0 -100 之间时,会提示: MyNumberException: 你输入的数不在 0 - 100 */ // ------------ /** 断言(assertion)在程序中只是一条语句,断言可以对布尔表达式进行检查。 一旦这个表达式的值为 false,就说明该程序已经处于不正确的状态, 会提示错误信息. 断言格式: 1. assert 布尔表达式; 2. assert 布尔表达式:细节描述信息; 如果布尔表达式的结果为 true,则没有任何错误提示信息, 若布尔表达式为 false,则会有错误提示信息。 如果在定义断言时没有声明细节信息, 那么系统将会使用默认的错误信息提示方式 断言返回的布尔值不能作为条件判断语句 */ public class Hi { public static void main(String[] args) { int score = 84; assert score > 85 : "是小于85的数"; } } /** -ea 表达开启断言,-da表示关闭断言,默认是关闭的 javac Hi.java java -ea Hi result Exception in thread "main" java.lang.AssertionError: 是小于85的数 at Hi.main(Hi.java:22) */ public class Hi { public static void main(String[] args) { int score = 84; assert score < 85; } }