一:异常的基本知识点
(1)异常是什么?
1.异常模拟的是现实世界中“不正常的”事件。
2.java中采用“类”去模拟异常。
3.类是可以创建对象的。
NullpointerException e = 0*12345;
e 是引用类型,e中保存的内存地址指向堆中的“对象”
这个对象一定是NullpointerException类型
NullpointerException是一类异常
例如:“抢劫”就是一类异常----->类
“张三被抢劫”就是一个异常事件----->对象
(2)什么是”调用栈"?
方法之间是存在相互调用关系的, 这种调用关系我们可以用 "调用栈" 来描述. 在 JVM 中有一块内存空间称为 "虚拟机栈" 专门存储方法之间的调用关系. 当代码中出现异常的时候, 我们就可以使用 e.printStackTrace(); 的方式查看出现异常代码的调用栈.
(3)已接触的异常
1.分母为0
System.out.println(10 / 0);
// 执行结果
Exception in thread "main" java.lang.ArithmeticException: / by zero
2.数组下标越界
int[] arr = {1, 2, 3};
System.out.println(arr[100]);
// 执行结果
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 100
3.访问null对象
public class Test {
public int num = 10;
public static void main(String[] args) {
Test t = null;
System.out.println(t.num);
}
}
//执行结果:
Exception in thread "main" java.lang.NullPointerException
(4)两种异常防御式编程
1.LBYL: Look Before You Leap. 在操作之前就做充分的检查.
2.EAFP: It's Easier to Ask Forgiveness than Permission. "事后获取原谅比事前获取许可更容易". 也就是 先操作, 遇到问题再处理.(是异常的核心思想)
(5)异常的继承(见下文三异常体系结构)
二:异常的基本用法
(1)捕捉异常(try... catch...)
1.基本语法:
try{
有可能出现异常的语句 ;
}[catch (异常类型 异常对象) {
} ... ]
}[catch (异常类型 异常对象) {
} ... ]
}[catch (异常类型 异常对象) {
} ... ]
[finally {
异常的出口
}]
//catch可以有一个或多个
解释:
try 代码块中放的是可能出现异常的代码.
catch 代码块中放的是出现异常后的处理行为.
finally 代码块中的代码用于处理善后工作, 会在最后执行.
其中 catch 和 finally 都可以根据情况选择加或者不加.
2.代码示例
不处理异常:一旦出现异常, 程序就终止了,无法正确输出异常之后的内容.
int[] arr = {1, 2, 3};//长度为3
System.out.println("before");
System.out.println(arr[10]);
System.out.println("after");
// 执行结果
before
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 10
//after没有输出
使用(try... catch...)处理异常
int[] arr = {1, 2, 3};
try {
System.out.println("before");
System.out.println(arr[100]);
System.out.println("after");
} catch (ArrayIndexOutOfBoundsException e) {//数组下标越界
// 打印出现异常的调用栈
e.printStackTrace();
}
System.out.println("after try catch");
// 执行结果
before
java.lang.ArrayIndexOutOfBoundsException: 100
at demo02.Test.main(Test.java:10)
after try catch
注意:一旦 try 中出现异常, 那么 try 代码块中的程序就不会继续执行, 而是交给 catch 中的代码来执行. catch 执行完毕会继续往下执行.
catch不能处理空指针异常
代码示例:
int[] arr = {1, 2, 3};
try {
System.out.println("before");
arr = null;//空指针
System.out.println(arr[100]);
System.out.println("after");
} catch (ArrayIndexOutOfBoundsException e) {
e.printStackTrace();
}
System.out.println("after try catch");
// 执行结果
before
Exception in thread "main" java.lang.NullPointerException
at demo02.Test.main(Test.java:11
注意:结果没有执行after try catch,说明catch 语句不能捕获到刚才的空指针异常. 因为异常类型不匹配。
catch可以只使用一个(不推荐)
代码示例:
int[] arr = {1, 2, 3};
try {
System.out.println("before");
arr = null;
System.out.println(arr[100]);
System.out.println("after");
} catch (Exception e) {//Exception是父类
e.printStackTrace();
}
System.out.println("after try catch");
// 执行结果
before
java.lang.NullPointerException
at demo02.Test.main(Test.java:12)
after try catch
注意:NullPointerException 和 ArrayIndexOutOfBoundsException 都是 Exception 的 子类, 因此都能被捕获到。
(2)throw关键字上抛异常
1.用法:定义一个方法的时候可以使用throws关键字声明。使用throws关键字声明的方法表示此方法不处理异常,而交给方法调用处进行处理。
2.语法示例:
public 返回值类型 方法名称(参数列表,,,)throws 异常类{};
3.代码示例:
public static void main(String[] args) {
System.out.println(divide(10, 0));
}
public static int divide(int x, int y) {
if (y == 0) {
throw new ArithmeticException("抛出除 0 异常");
}
return x / y;
}
// 执行结果
Exception in thread "main" java.lang.ArithmeticException: 抛出除 0 异常
at demo02.Test.divide(Test.java:14)
at demo02.Test.main(Test.java:9)
(3)异常机制有什么作用?
程序发生异常事件后,为我们输出详细的信息,程序员通过这个信息,可以对程序进行一些处理,使程序更加健壮。
代码示例:
int a = 10;
int b = 0;
if(b != 0){
int c = a/b;
System.out.println(a + "/" + b "=" + c);
}else{
System.out.println("除数不能为0");
}
三:java的异常体系结构
1.Java 内置的异常类之间的继承关系:
2.解释:
顶层类 Throwable 派生出两个重要的子类, Error 和 Exception。
Error 指的是 Java 运行时内部错误和资源耗尽错误. 应用程序不抛出此类异常. 这种内部错误 一旦出现,除了告知用户并使程序终止之外, 再无能无力. 这种情况很少出现。
Exception 是我们程序猿所使用的异常类的父类。
Exception 有一个子类称为 RuntimeException , 这里面又派生出很多我们常见的异常类 NullPointerException , IndexOutOfBoundsException 等。
四:自定义异常类
1.定义:除了java中的异常类之外,我们实际场景中可能还有一些情况需要我们对异常类进行扩 展, 创建符合我们实际情况的异常。
2.代码示例:
public class Test {
private static String userName = "admin";
private static String password = "123456";
public static void main(String[] args) {
login("admin", "123456");
}
public static void login(String userName, String password) {
if (!Test.userName.equals(userName)) {
// TODO 处理用户名错误
}
if (!Test.password.equals(password)) {
// TODO 处理密码错误
}
System.out.println("登陆成功");
}
}
3.注意:
自定义异常通常会继承自 Exception 或者 RuntimeException。
继承自 Exception 的异常默认是受查异常。
继承自 RuntimeException 的异常默认是非受查异常。