异常
异常概述
就是程序出现了不正常的情况。程序在执行过程中,出现的非正常的情况,最终会导致 JVM 的非正常停止。
注意:语法错误不算在异常体系中。
Error:严重问题,通过代码无法处理。比如:内存溢出。
Exception:称为异常类,它表示程序本身可以处理的问题。
RuntimeException及其子类:运行时异常。 (空指针异常,数组索引越界异常)
除RuntimeException之外所有的异常:编译期必须处理的,否则程序不能通过编译。(日期格式化异常)。
编译时异常和运行时异常
编译时异常,是在编译成class文件时必须要处理的异常,也称之为受检异常
运行时异常,在编译成class文件不需要处理,在运行字节码文件时可能出现的异常。也称之为非受检异常
JVM 的默认处理方案
将异常的名称,异常原因及异常出现的位置等信息以红色字体打印在控制台;结束程序运行。
异常处理方式
一、抛出 throws、throw
throws
格式:throws 异常类名 (这个格式是写在方法的定义处,表示声明一个异常。)
运行时异常因为在运行时才会发生,所以在方法后面可以不写
1 public class ExceptionDemo1 { 2 public static void main(String[] args) { 3 method1(); //此时调用者也没有处理.还是会交给虚拟机处理. 4 } 5 6 //告诉调用者,你调用我,有可能会出现这样的异常哦. 7 //如果方法中没有出现异常,那么正常执行 8 //如果方法中真的出现了异常,其实也是将这个异常交给了调用者处理. 9 //private static void method1() throws NullPointerException { 10 //如果声明的异常是一个运行时异常,那么声明的代码可以省略 11 private static void method1() /*throws NullPointerException*/ { 12 int [] arr = null; 13 for (int i = 0; i < arr.length; i++) { 14 System.out.println(arr[i]); 15 } 16 } 17 }
编译时异常因为在编译时就会检查,所以必须要写在方法后面进行显示声明
1 public class ExceptionDemo2 { 2 public static void main(String[] args) throws ParseException { 3 method2(); //还是继续交给调用者处理.而main方法的调用者是虚拟机还是会采取虚拟机默认处理异常的方法. 4 } 5 6 //告诉调用者,你调用我,有可能会出现这样的异常哦. 7 //如果方法中没有出现异常,那么正常执行 8 //如果方法中真的出现了异常,其实也是将这个异常交给了调用者处理. 9 //如果声明的异常是一个编译时异常,那么声明的代码必须要手动写出. 10 private static void method2() throws ParseException { 11 SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日"); 12 sdf.parse("2048-10月10日"); 13 } 14 }
throw-抛出异常对象
格式:throw new 异常() (这个格式是在方法内的,表示当前代码手动抛出一个异常,下面的代码不用再执行了。)
1 public class ExceptionDemo3 { 2 public static void main(String[] args) { 3 int [] arr = null; 4 printArr(arr);//2.接收到一个异常. 5 } 6 7 private static void printArr(int[] arr) { 8 if(arr == null){ 9 throw new NullPointerException(); //1.当参数为null的时候,手动创建了一个异常对象,抛给了调用者. 10 }else{ 11 for (int i = 0; i < arr.length; i++) { 12 System.out.println(arr[i]); 13 } 14 } 15 } 16 }
throws 和 throw 的区别
throws:
用在方法声明后面,跟的是异常类名
表示声明异常,调用该方法有可能会出现这样的异常
throw:
用在方法体内,跟的是异常对象名
表示手动抛出异常对象,由方法体内的语句处理
二、捕获 try…catch…
格式:
try {
可能出现异常的代码;
} catch(异常类名 变量名) {
异常的处理代码;
}
好处:可以让程序继续往下执行。
1 public class ExceptionDemo4 { 2 public static void main(String[] args) { 3 int [] arr = null; 4 try{ 5 //有可能发现异常的代码 6 printArr(arr); 7 }catch (NullPointerException e){ 8 //如果出现了这样的异常,我们进行的操作 9 System.out.println("参数不能为null"); 10 } 11 } 12 13 private static void printArr(int[] arr) { 14 if(arr == null){ 15 throw new NullPointerException(); 16 }else{ 17 for (int i = 0; i < arr.length; i++) { 18 System.out.println(arr[i]); 19 } 20 } 21 } 22 }
注意:
1.如果 try 中没有遇到问题,怎么执行?
会把try中所有的代码全部执行完毕,不会执行catch里面的代码
2.如果 try 中遇到了问题,那么 try 下面的代码还会执行吗?
那么直接跳转到对应的catch语句中,try下面的代码就不会再执行了
当catch里面的语句全部执行完毕,表示整个体系全部执行完全,继续执行try...catch外的代码
3.同时有可能出现多个异常怎么处理?
出现多个异常,那么就写多个catch就可以了.
注意点:如果多个异常之间存在子父类关系.那么父类一定要写在下面
Throwable 的成员方法
public String getMessage() 返回此 throwable 的详细消息字符串
public String toString() 返回此可抛出的简短描述
public void printStackTrace() 把异常的错误信息输出在控制台(字体为红色的)
1 public class ExceptionDemo { 2 public static void main(String[] args) { 3 try { 4 int [] arr = {1,2,3,4,5}; 5 System.out.println(arr[10]);//虚拟机帮我们创建了一个异常对象 new ArrayIndexOutOfBoundsException(); 6 } catch (ArrayIndexOutOfBoundsException e) { 7 /*String message = e.getMessage(); 8 System.out.println(message);*/ 9 /* String s = e.toString(); 10 System.out.println(s);*/ 11 e.printStackTrace(); 12 } 13 } 14 }
自定义异常
步骤:
1.定义异常类
2.写继承关系
3.空参构造
4.带参构造
1 public class AgeOutOfBoundsException extends RuntimeException { 2 public AgeOutOfBoundsException() { 3 } 4 public AgeOutOfBoundsException(String message) { 5 super(message); 6 } 7 }