目录
1、异常体系介绍
1.1、异常是什么?
1.2、运行时异常和编译时异常的区别?
2、异常的用法
2.1、捕获异常
2.2、异常中的常见方法
2.3、抛出异常
2.4、自定义异常
1、异常体系介绍
1.1、异常是什么?
java异常是指在程序运行时可能出现的一些错误,如:文件找不到、网络连接失败、非法参数等。异常是一个事件,它发生在程序运行期间,中断了正在执行的程序的正常指令流。Java通过API中Throwable类的众多子类描述各种不同的异常。因而,Java异常都是对象,是Throwable子类的实例,描述了出现在一段编码中的错误条件。当条件生成时,错误将引发异常。
简单来说,异常就是程序中可能出现的问题。
Java异常类层次结构图
Java所有异常类都是 Throwable的子类,两个重要的子类是:Error 和 Exception
Error:Error及其子类用来描述Java运行系统中的内部错误以及资源耗尽的错误,代表的系统级别错误,是程序无法处理的错误(这属于严重问题,系统一旦出现这种问题,Java虚拟机(JVM)一般会选择线程终止。)
Exception:这类异常可以通过捕捉处理使程序继续执行,是程序自身可以处理的异常,也称为非致命性异常类。根据错误发生原因可分为运行时异常(RuntimeException)和除RunTimeException之外的编译时异常
就是说异常与错误是有区别的,异常可以通过程序自身捕捉处理,而错误是程序自身无法处理的。
1.2、运行时异常和编译时异常的区别?
运行时异常:RuntimeException本身和其子类;运行时异常在编译阶段没有错误提示,因为Java编译器不会检查它,当程序中出现这类异常时,也会编译通过,在运行时这类异常才会出现错误提示;一般是由于参数传递错误带来的问题
编译时异常:这类异常是没有继承RuntimeExcpetion的异常,直接继承于Excpetion;在编译阶段需要进行处理,然后就会错误提示,作用在于提醒程序员
程序中应当尽可能去处理这两种异常
异常的作用:
(1)异常是用来查询bug的关键参考信息
(2)异常可以作为方法内部的一种特殊返回值,以便通知调用者底层的执行情况
2、异常的用法
2.1、捕获异常
捕获异常书写格式:
try {
//可能出现异常的代码;
} catch(异常类名 变量名){
//异常的处理代码;
} finally {
//不管前面的try有没有捕获到异常,被finally控制的语句一定会执行,除非IVM退出
}
捕获异常的目的:当代码出现异常时,可以让程序继续往下执行。
捕获异常示例:
在下面代码中的try中写了一条有数组越界异常的代码,然后用catch去捕获异常,看看之后的代码会不会继续执行
public static void main(String[] args) {int[] arr = {1,3,2,4,5};try {System.out.println(arr[10]);//此处出现了异常,程序就会在这里创建一个ArrayIndex0utOfBoundsException对象//new ArrayIndexOutofBoundsException();//拿着这个对象到catch的小括号中对比,看括号中的变量是否可以接收这个对象1//如果能被接收,就表示该异常就被捕获(抓住),执行catch里面对应的代码//当catch里面所有的代码执行完毕,继续执行try...catch体系下面的其他代码} catch (ArrayIndexOutOfBoundsException e) {//如果出现了ArrayIndex0utOfBoundsException异常,我该如何处理System.out.println("索引越界了");}System.out.println("看看我执行了吗");
}
运行结果
捕获异常时的各种情况 :
(1)如果try中没有遇到问题,系统会把try里面所有的代码全部执行完毕,不会执行catch里面的代码。注意:只有当出现了异常才会执行catch里面的代码
(2)如果try中遇到多个问题,要写多个catch与之对应,并且如果我们要捕获多个异常,这些异常中如果存在父子关系的话,那么父类一定要写在下面。了解:在JDK7之后,我们可以在catch中同时捕获多个异常,中间用 | 进行隔开表示如果出现了A异常或者B异常的话,采取同一种处理方案
(3)如果try中遇到的问题没有被捕获,相当于try...catch的代码白写了,最终还是会交给虚拟机进行处理。
(4)如果try中遇到了问题,那么下面的代码就不会执行了,直接跳转到对应的catch当中,执行catch里面的语句体,但是如果没有对应catch与之匹配,那么还是会交给虚拟机进行处理。
2.2、异常中的常见方法
Throwable 的成员方法
方法名称 ;说明
public String getMessage()返回此 throwable 的详细消息字符串
public string toString()返回此可抛出的简短描述
public void printStackTrace()把异常的错误信息输出在控制台
注意:仅仅是打印出错误信息,并不会停止程序运行
方法示例:
public String getMessage()和 public string toString()示例
public static void main(String[] args) {int[] arr = {1,3,2,4,5};try {System.out.println(arr[10]);} catch (ArrayIndexOutOfBoundsException e) {String message = e.getMessage();System.out.println(message);//打印 Index 10 out of bounds for length 5String str = e.toString();System.out.println(str);//打印 java.lang.ArrayIndexOutOfBoundsException: Index 10 out of bounds for length 5//e.printStackTrace();}System.out.println("看一下我执行了没有");
}
结果:
public void printStackTrace()示例
public static void main(String[] args) {int[] arr = {1,3,2,4,5};try {System.out.println(arr[10]);} catch (ArrayIndexOutOfBoundsException e) {e.printStackTrace();}System.out.println("看一下我执行了没有");
}
结果:
扩展:用System.err.println打印出来的信息是红色的
//正常的输出语句
System.out.println(123);
//错误的输出语句(而是用来打印错误信息)
System.err.println(123);
2.3、抛出异常
抛出异常处理有两种方式是:throw 和 throws
throws
注意:写在方法定义处,表示声明一个异常
告诉调用者,使用本方法可能会有哪些异常
public void 方法()throws 异常类名1,异常类名2 . . . {
. . .
}
编译时异常:必须要写;运行时异常:可以不写。
throw
注意:写在方法内,结束方法
手动抛出异常对象,交给调用者
方法中下面的代码不再执行了
public void 方法(){
throw new NullPointerException();
}
示例:
public static void main(String[] args) {// 需求:// 定义一个方法求数组的最大值int[] arr = {};int max = 0;try {max = getMax(arr);} catch (NullPointerException e) {System.out.println("数组空指针异常");} catch (ArrayIndexOutOfBoundsException e) {System.out.println("数组索引越界异常");}System.out.println(max);
}public static int getMax(int[] arr) {if (arr == null) {//手动创建一个异常对象,并把这个异常交给方法的调用者处理//此时方法就会结束,下面的代码不会再执行了throw new NullPointerException();}if (arr.length == 0) {//手动创建一个异常对象,并把这个异常交给方法的调用者处理//此时方法就会结束,下面的代码不会再执行了throw new ArrayIndexOutOfBoundsException();}int max = arr[0];for(int i=1; i<arr.length; i++) {if (max < arr[i]) {max = arr[i];}}return max;
}
2.4、自定义异常
自定义异常书写步骤:
(1)定义异常类
(2)写继承关系
(3)空参构造
(4)带参构造
自定义异常定义时取名意义:就是为了让控制台的报错信息更加的见名之意
示例:
自定义异常NameFormException
public class NameFormException extends RuntimeException{//技巧://NameFormat:当前异常的名字,表示姓名格式化问题//Exception:表示当前类是一个异常类//运行时:自定义的异常就继承 RuntimeException 核心 就表示由于参数错误而导致的问题//编译时:自定义的异常就继承 Exception 核心 提醒程序员检查本地信息public NameFormException() {}public NameFormException(String message) {super(message);}
}
自定义AgeOutOfBoundsException
public class AgeOutOfBoundsException extends RuntimeException{public AgeOutOfBoundsException() {}public AgeOutOfBoundsException(String message) {super(message);}
}
定义Student类,如果在给属性name和age赋值时,数据不符合要求时就抛出相应的自定义异常
public class Students {private String name;private int age;public Students() {}public Students(String name, int age) {this.name = name;this.age = age;}public String getName() {return name;}public void setName(String name) {int len = name.length();if (len < 3 || len >10) {throw new NameFormException(name + "格式有误,名字长度应为3~10");}this.name = name;}public int getAge() {return age;}public void setAge(int age) {if (age < 18 || age > 40) {throw new AgeOutOfBoundsException(age + "超出18~40这个范围");}this.age = age;}public String toString() {return "student{ name = " + name + ", age = " + age + " }";}
}
测试类Test
public class Test {public static void main(String[] args) {//1.创建键盘录入的对象ScannerScanner sc = new Scanner(System.in);//2.创建学生的对象Students stu = new Students();while (true) {try {System.out.println("请输入学生姓名");String name = sc.nextLine();stu.setName(name);System.out.println("请输入学生年龄");String ageStr = sc.nextLine();int age = Integer.parseInt(ageStr);stu.setAge(age);//如果所有的数据都是正确的,那么跳出循环break;} catch (NumberFormatException e) {e.printStackTrace();} catch (NameFormException e) {e.printStackTrace();} catch (AgeOutOfBoundsException e) {e.printStackTrace();}}System.out.println(stu);}
}
推荐:
【计算机网络】DHCP原理与配置-CSDN博客https://blog.csdn.net/m0_65277261/article/details/136230649?spm=1001.2014.3001.5501
【数据结构】二叉查找树和平衡二叉树,以及二者的区别_二叉查找树和其他二叉树的区别-CSDN博客https://blog.csdn.net/m0_65277261/article/details/136137098?spm=1001.2014.3001.5501
【数据结构】前缀树的模拟实现-CSDN博客https://blog.csdn.net/m0_65277261/article/details/136086068?spm=1001.2014.3001.5501