前言
温故而知新,异常是Java的入门知识,熟练的掌握可以有效的处理程序中的运行错误,添加代码的健壮性。
这里主要记录下自己的学习,理解以及总结。
一、什么是异常?
异常:程序出现的不正常情况。
二、异常的架构
1、Throwable
Throwable类是Java语言中所有错误和异常的父类。
2、Error
Error(错误),错误的发生,只有一个结果,那就是程序终止退出。这种错误无法恢复或不可能捕获,将导致应用程序中断,通常不处理。因为如果出现这样的内部错误,除了通告用户,并尽力使程序安全地终止之外,再也无能为力了。
3、Exception
表示程序本身可以处理的问题,这里分为编译异常以及运行异常。
三、常见Error和Exception
1、运行异常(RunTtimeException)
-
NullPropagation:空指针异常;
-
ClassCastException:类型强制转换异常
-
IllegalArgumentException:传递非法参数异常
-
IndexOutOfBoundsException:下标越界异常
-
NumberFormatException:数字格式异常
2、编译异常
-
ClassNotFoundException:找不到指定 class 的异常
-
IOException:IO 操作异常
3、错误(Error)
-
NoClassDefFoundError:找不到 class 定义异常
-
StackOverflowError:深递归导致栈被耗尽而抛出的异常
-
OutOfMemoryError:内存溢出异常
四、异常处理
1、throws方式处理异常
格式
public void 方法() throws 异常类名 {
}
示例
public static void main(String[] args) throws ParseException {
int[] arr = { 0, 1, 2 };
System.out.println("开始");
System.out.println(arr[3]);
System.out.println("访问到这里!");
}
运行结果以及分析
程序执行到System.out.println(arr[3]);
此处发生了 异常。
throws的格式是跟在方法的括号后面的,发生异常方法停止后续的代码不执行。
在方法声明的位置上使用 throws
关键字抛出,谁调用我这个方法,我就抛给谁。抛给 调用者
来处理。
2、throw抛出异常
格式
throw new 异常();
throws和throw区别
throws | throw |
用在方法声明后面,跟的是异常类名 | 用在方法体内,跟的是异常对象名 |
表示声明异常,调用该方法有可能会出现这样的异常 | 表示手动抛出异常对象,由方法体内的语句处理 |
代码
普通代码
public static void main(String[] args) throws ParseException {
int[] arr = { 0, 1, 2 };
int i=3;
if(i>arr.length-1) {
System.out.println("数组下标越界");
}else{
System.out.println(arr[3]);
}
}
运行结果: 数组下标越界
改造代码一
public static void main(String[] args) throws ParseException {
int[] arr = { 0, 1, 2 };
int i=3;
if(i>arr.length-1) {
System.out.println("数组下标越界");
throw new ArrayIndexOutOfBoundsException();
}else{
System.out.println(arr[3]);
}
}
改造代码二
public static void main(String[] args) throws ParseException {
int[] arr = { 0, 1, 2 };
int i=3;
if(i>arr.length-1) {
System.out.println("数组下标越界");
//throw new ArrayIndexOutOfBoundsException();
throw new NullPointerException();
}else{
System.out.println(arr[3]);
}
}
说明
这个格式是在方法内的,表示当前代码手动抛出一个异常,下面的代码不用再执行了 ,因为是开发者编写的手动抛出,所以异常的定义可以随意(由示例中可以看出)。比如有的方法中有向数据库添加数据的操作,这里如果产生异常在catch里面会要求加上throw,终止程序的进行。
3、try-catch方式处理异常
格式
try {
可能出现异常的代码;
} catch(异常类名 变量名) {
异常的处理代码;
}
执行流程
- 程序从try里面的代码开始执行
- 出现异常后,就会跳转到对应的catch里面执行
- 执行完毕之后,程序还可以继续往下执行
示例
public class ExceptionDemo {
public static void main(String[] args) {
int[] arr= {0,1,2};
System.out.println("开始");
try {
System.out.println(arr[3]);
System.out.println("访问到这里!");
} catch (Exception e) {
System.out.println("数组打印异常了!");
}
System.out.println("结束");
}
}
运行结果以及分析
首先用正常运行代码(上述改为arr[2]),执行结果为:
把try中所有的代码全部执行完毕,不会执行catch里面的代码。
按照图片代码执行记过
由结果可知arr[3]后面的代码没有执行,catch里面代码执行了,程序正常运行。符合执行流程中的说明。
- catch可以写多个。建议catch的时候,精确的一个一个处理。这样有利于程序的调试。
- catch写多个的时候,从上到下,必须遵守
从小到大
。 - JDK8的新特性:catch() 异常间可以自小到大用
|
分割
五、finally关键字
在finally子句中的代码是最后执行的,并且是 一定会执行
的,即使try语句块中的代码出现了异常。
finally子句必须和try一起出现,不能单独编写。
注意:
1 finally不能单独使用,必须和try一起使用
2 finally一般用于资源释放(资源回收),无论程序是否出现异常,最后都需要资源释放(IO)
3 如果finally有return语句,永远返回finally中的结果(避免该情况)。
六、自定义异常
public class AgeOutOfBoundsException extends RuntimeException{
public AgeOutOfBoundsException() {
}
public AgeOutOfBoundsException(String message) {
super(message);
}
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入年龄");
String Str = sc.nextLine();
try {
int age = Integer.parseInt(Str);
auditAge(age);
} catch (NumberFormatException e) {
System.out.println("请输入一个整数");
} catch (AgeOutOfBoundsException e) {
System.out.println("年龄超出了范围");
}
}
private static void auditAge(int age) {
if(age > 100 ){
//如果Java中提供的异常不能满足我们的需求,我们可以使用自定义的异常
throw new AgeOutOfBoundsException("年龄超出了范围");
}
}