什么是异常?
代码在运行时产生的错误,它中断正在执行的程序的正常指令流。
异常和错误的区别
编译时产生的是错误(Error),运行时产生的是异常(Exception)。
但是一般都讲错误(Error)当成是异常的一种。
Java异常
在Java中,所有的异常都是属于Throwable类里面的,Throwable 中有两个子类: Error和Exception。
Error是在编译时产生的,属于系统中严重的错误,会使JVM无法运行。
Exception 子类包含了一个叫RuntimeException的子类和其他多种子类。除了RuntimeException子类属于运行时异常,其他子类则属于编译时异常。
注意:程序一旦发生异常就会中断,后面的代码就不会执行。
关系图
异常解决手段
try-catch
try 块可以说是监控区域。用来监控在try内的代码。如果出现了异常,那么程序不会马上中断,而是进入到catch块中对异常进行处理或其他操作,catch 块可以说是异常处理区域。
public class ExceptionDemo1 {
public static void main(String[] args) {
demo3();
}
private static void demo3() {//空指针异常
try {
int[] nums = new int[]{1, 2, 3};
nums = null;//把数组地址设为空。
System.out.println(nums[2]);
System.out.println("测试");
} catch (Exception e) {
e.printStackTrace();//这句话是抛出异常信息(抛出为什么会异常)
System.err.println("空指针异常");
}
}
测试结果
从上面的案例可以看出,当程序异常的时候try内在System.out.println(nums[2]);发生异常,try内从这往后的代码都不会执行,因为这是程序进入到catch中进行异常处理。
try…catch…finally处理异常
前面的try-catch中异常机制有个很大的弊端就是在使用终止处理机制的时候万一异常过早抛出,那么try内的一些有必要执行的代码就无法执行。那么这是finally就很重要了,因为finally内的代码不论try是否异常都会执行一遍。
public class ExceptionDemo1 {
public static void main(String[] args) {
demo1();
}
private static void demo1() {//算术异常
try {
int num = 10 / 0;
System.out.print("结果是:");
System.out.println(num);
} catch (Exception e) {
e.printStackTrace();//输出异常信息
System.out.println("被除数不能是0");
}finally {
System.out.println("测试finally会执行");//证明异常处理后程序不会被中断
}
}
测试结果
手动抛出异常与自定义异常类
通俗来讲,方法中抛出异常并没有“解决问题”,而是把问题“甩锅”出去,谁调用谁负责处理这个“锅”,当然调用者(方法)可以再次“甩锅”出去,直到最后一个(方法),最后一个不能再“甩”了,就要用try-catch来“解决问题”。(甩锅这个是我老师的比喻,我觉得挺好,这里算是借鉴他老人家的话,哈哈哈)。
抛出异常的方法:
throw是在程序代码中手动抛出异常(代码级别)。
throws Exception(甩锅处理,方法级别)。
废话少说,直接上代码解释:
/*
定义一个邮件地址异常类,当用户输入个邮件地址不合法时,抛出异常。
*/
public class Work3 {
public static void address() throws EmailAddressException {手动抛出异常
System.out.println("请输入邮件地址:");
Scanner sc = new Scanner(System.in);
String addre = sc.nextLine();
String regex = "\\w+@\\w+(\\.[a-z]{2,3}){1,2}";
if (addre != regex) {
throw new EmailAddressException("邮件地址不合法");//手动抛出异常
}
}
public static void main(String[] args) {
//因为以前都是“甩锅”。所以现在主方法要调用,那就要try-catch来接收异常。
try {
address();
} catch (EmailAddressException e) {
System.out.println(e.getMessage());
}
}
}
class EmailAddressException extends Exception{//自定义异常类
public EmailAddressException(String s){
super(s);//要调用父类
}
}