1.基本概念
开发过程中程序运行不正常的情况:
①错误Error:由非代码问题所造成的不正常:如内存溢出、断电…等等。
特点:出现问题不能由代码进行恢复
②异常Exception:由代码问题所造成的不正常
特点:可以通过代码进行修正
错误Error和异常Exception都是继承了Throwable。
2.异常的分类
1)运行时异常(未检查异常)
程序在编译的时候未检查出的异常,只有在程序运行的过程中才会出现问题,当项目上线前程序中不允许出现运行时异常。
常见的运行时异常:
ArithmeticException
ArrayIndexOutOfBoundsException
IndexOutOfBoundsException
NullPointerException
ClassCastException
运行时异常的父类:RuntimeException extends Exception
2)编译时异常(已检查异常)
程序在编译的时候已经检查出当前程序有可能会出现的问题,当前程序会要求调用者给出如果出现问题时的处理方式。
当程序出现编译时异常,则需要处理异常(告诉程序当出现错误时如何处理)
编译时异常直接继承Exception
3.异常的抛出和传递
1)异常抛出
package Review.ExceptionTest;
public class ThrowTest {
public static void main(String[] args) {
divide(12,3);
divide(12,0);
}
public static int divide(int a,int b) {
if(b==0) {
throw new ArithmeticException();// 异常抛出通过throw关键字,并在其创建要抛出异常的对象
}else {
return a/b;
}
}
}
运行结果:
Exception in thread "main" java.lang.ArithmeticException
at Review.ExceptionTest.ThrowTest.divide(ThrowTest.java:13)
at Review.ExceptionTest.ThrowTest.main(ThrowTest.java:8)
2)异常的传递
当函数嵌套调用时,如果其中一个函数出现了异常,则调用该函数的所有方法都会产生异常
package Review.ExceptionTest;
public class ThrowTest {
public static void main(String[] args) {
a(12,0);
}
public static void a(int a,int b) {
System.out.println("----a----");
divide(a,b);
System.out.println("----b----");
}
public static void divide(int a,int b) {
if(b==0) {
throw new ArithmeticException();
}else {
System.out.println(a/b);
}
}
}
运行结果:
----a----
Exception in thread "main" java.lang.ArithmeticException
at Review.ExceptionTest.ThrowTest.divide(ThrowTest.java:19)
at Review.ExceptionTest.ThrowTest.a(ThrowTest.java:14)
at Review.ExceptionTest.ThrowTest.main(ThrowTest.java:7)
3)异常信息的分析
当控制台出现异常时:
4.异常处理
如果是运行时异常,出现异常后需要通过代码进行改正。然而异常处理主要是针对编译时异常进行。
异常处理的方式:
1)throws
public static void divide(int a,int b) throws FileNotFoundException {
if(b==0) {
throw new FileNotFoundException(); // 编译时异常,通过throws关键在方法声明时将其抛出
}else {
System.out.println(a/b);
}
==需要注意的是:==这种异常处理的方式并没有真正意义上地解决异常,如果在嵌套调用函数过程中,一个函数是以此方式处理异常的话,那么调用该函数的函数还是要给出异常处理的方法。
2)try…catch…finally
因为上述异常处理的方式中,只是把异常抛给另外一个需要调用它的函数,而在真正意义上并没有解决异常。所以才有了try…catch…finally。
①基本结构
②try…catch的特征
(1)try中可以产生多种异常,此时通过多个catch进行捕获处理
(2)try中的异常类型和catch中的异常类型要一一对应
(3)catch中可以通过定义多个try中出现异常的父类来处理异常
(4)多个catch中出现的异常类型要么平级要么从小到大排列
(5)语法上catch是可以省略的
③finally的特征
(1)finally可以省略
(2)不管try中是否有return语句,finally语句块都会执行
package Review.ExceptionTest;
import java.io.FileNotFoundException;
public class ThrowTest {
public static void main(String[] args) {
a(12,0);
}
public static void a(int a,int b) {
System.out.println("----a----");
divide(a,b);
System.out.println("----b----");
}
public static void divide(int a,int b) {
if(b==0) {
try {
throw new FileNotFoundException(); // 可能会出现异常的代码。当异常运行后,异常后面的语句块不再运行,为不可达语句
} catch (FileNotFoundException e) { // 当出现异常时catch后面的语句块是补救措施
e.printStackTrace();
}finally {
System.out.println("我一定会执行!!!");
}
}else {
System.out.println(a/b);
}
}
}
运行结果:
----a----
java.io.FileNotFoundException
at Review.ExceptionTest.ThrowTest.divide(ThrowTest.java:25)
at Review.ExceptionTest.ThrowTest.a(ThrowTest.java:16)
at Review.ExceptionTest.ThrowTest.main(ThrowTest.java:9)
我一定会执行!!!
----b----
3)异常信息输出
5.方法重写异常
在方法重写中,子类抛出的异常类型要小于等于父类抛出的异常。同访问修饰符对比记忆
特殊情况:如果重写方法中抛出的异常是平级的不同类型异常也是重写方法
6.自定义异常
执行定义一种情况来构建成一个异常类型
需求:我可以接受一个年龄来判断当前年龄是否是成人年龄
编译时异常:extends Exception
运行时异常:extends RuntimeException