1. 异常
异常是代码在编译或者执行的过程中可能出现的错误,在java中,异常其实也是一种类。
- 异常的最大类叫Throwable(可抛出的),其下又分为Error(错误,大部分由硬件问题导致)和 Exception(程序中出现的异常)
- 我们需要关心的就是Exception,其可以分为两类,一类是RunTimeException,以及其他异常。
- RunTimeException其实就是运行时异常,通常是常识性错误,在编译时不会报错,在运行时会报错。
- 其他异常,其实就是编译时异常,在编译时我们就必须对其进行处理,此时还可能需要通过专业的学习才能处理异常,后续会学习抛出异常和抓取异常。
JVM遇到异常会怎么做?
答:虚拟机遇到异常会终止程序,且会打印异常信息。
对于运行时异常,JVM会直接帮助我们抛出,而对于编译时异常,通常会我们自己通过抓或者抛的操作进行处理
展示异常:
//运行时异常
public static void main(String[] args) {
int[] arr = new int[3];
System.out.println(arr[3]);
}//mian
//展示错误类型:ArrayIndexOutOfBoundsException,
//位置:ExceptionAge.java:8
//错误原因Index 3 out of bounds for length 3
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 3 out of bounds for length 3
at cn.itcast.practice.ExceptionAge.main(ExceptionAge.java:8)
//对于编译时异常,我们后续自己造异常时可以再举例,老师用的是 日期格式举例
public static void main(String[] args) throws ParseException {
//此时如果不处理,将会无法通过编译
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date date = sdf.parse("2020年01月01日 12:12:12");
}
2. 处理异常(抛、抓)
-
作为某个方法的调用者,可能会出现编译时异常,我们必须对于异常进行处理。
-
如果为第三方提供我们的工具类方法时,担心第三方使用时会胡乱使用我们的工具类,我们在工具类方法书写时,也就需要对于可能出现的异常情况进行处理。
(一)抛出异常:
throws
关键字被用于方法签名中,以声明该方法可能会抛出的异常类型。
补充:对于我们在日常写代码时,如果遇到编译时异常,可以使用快捷键alt+anter可以把异常直接抛到方法签名中。
(二)抓取异常:
- 抓取异常的优势就在于不会终止程序!!!
- 抓取异常可以有多个catch,但是需要子类异常需要出现在上面
//展示抓取异常
public static void main(String[] args) {
int age;
Scanner sc = new Scanner(System.in);
System.out.println("请输入你的年龄");
try {
age = sc.nextInt();
if (age > 0 && age <=150){
System.out.println("你的年龄为"+age);
}else {
System.out.println("你输入的年龄不在正常年龄范围之内");
}
} catch (Exception e) {
System.out.println("你输入的数据类型不对");
throw new RuntimeException(e);
}
System.out.println("无论异常与否,都会执行的代码");
}//main
获取异常的对象e后,可以输出不同的信息
- getMessage(); 获取异常原因
- toString(); 获取类型和原因
- printStackTrace(); 控制台直接打印获取异常原因,位置,类型,异常信息
3. 自定义异常/造异常
之前我们提到,异常也是一种类,自然我们可以进行书写自己的异常种类。
操作:
- 定义一个见名知意的异常类名,选择继承Exception(编译时异常)或者RuntimeException(运行时异常)
- 重写其父类的构造方法
补充:对于自定义的编译时异常,是常常写在方法中的,通过方法上添加throws关键字,方法的调用者则必须处理这个编译时异常,但是对于运行时异常,我们可以直接通过判断条件,通过throw new 异常类名;进行抛出,此时可以不在方法签名添加thows关键字。
自定义异常举例:
//先创建一个见名知意的异常名,且重写抽象方法
package cn.itcast.practice;
public class ArrayIsNullorLengthIZero extends RuntimeException{
public ArrayIsNullorLengthIZero() {
}
public ArrayIsNullorLengthIZero(String message) {
super(message);
}
}
//创建一个工具类,书写可能会出现异常的方法
package cn.itcast.practice;
public class ArrayUtils {
public static int getMax(int[] arr) throws ArrayIsNullorLengthIZero {
if(arr == null || arr.length == 0){
throw new ArrayIsNullorLengthIZero("你的数组为null或者数组长度为0");
}
int max = arr[0];
for (int i = 0; i < arr.length; i++) {
max = max > arr[i] ? max:arr[i];
}
return max;
}
}
//进行测试
public class ArrayUtilTest {
public static void main(String[] args) {
int[] arr1 =new int[0];
System.out.println(ArrayUtils.getMax(arr1));
}//main
}
//如果此异常是编译时异常,就需要在测试时选择直接抛出或者抓取异常抛出
该造编译时异常还是运行时异常?
应该取决于异常的具体情况,如果是常识性问题,就属于运行时异常,继承RuntimeException(运行时异常)
如果是编译时需要注意的复杂情况,就需要继承Exception(编译时异常),强制调用者进行学习,以及处理异常。