1. 什么是异常?
2. Java 的异常体系
别担心 ,用的多了就记住啦 ~~
3. 异常的分类
异常分为:运行时异常 和 编译时异常
(1)运行时异常
运行时异常 :指程序在运行起来之后所抛出的异常,属于 非受查异常
(2)编译时异常
编译时异常 :在程序编译时抛出的异常,属于 受检查异常,换句话说,这类异常在出现时,程序猿必须进行处理,否则,程序不能通过编译;
(3)两者之间的区别
运行时异常 与 编译时异常 的区别
编译时异常 | 运行时异常 |
---|
发生概率高 | 一般不发生 | 发生之后需进行显示处理(try-catch/上报) | 不需要进行预处理 |
有关异常
(1) 如何抛出异常?
Java 中使用 throw 关键字来抛出一个异常;
如下所示:
(2) 如何声明异常–throws
使用 throws 关键字, 把可能要抛出的异常显式标注在方法定义的位置,从而提醒调用者捕获这些异常
举例:
public static void testThrows() throws ArrayIndexOutOfBoundsException{
int[] arr={1,2,3,4,5};
System.out.println(arr[6]);
}
注意:
-
throws 须跟在方法的参数列表之后 -
声明的异常必须是Exception 或 Exception的子类 -
throws 之后可以跟多个异常类型,中间用逗号隔开,若这些异常具有继承关系,直接声明父类即可 -
调用者需要对异常进行处理,或者直接采用继续向上抛出 - 处理态度 :上报
(3) 如何捕获异常----try-catch
try{
有可能出现异常的语句 ;
}catch (要捕获的异常类型1 e) {
} catch (要捕获的异常类型2 e) {
}finally {
此处代码一定会执行
}
catch 可以有多个,用来捕获不同的异常类型信息
public class Demo01 {
public static void method(){
try{
int[] array={1,2,3};
System.out.println(array[100]);
}catch(ArrayIndexOutOfBoundsException e){
e.printStackTrace();
}catch(NullPointerException e){
e.printStackTrace();
}
finally{
System.out.println("============");
}
}
public static void main(String[] args) {
method();
}
}
当执行此代码时,会有以下结果:
当上述代码执行数组为空,并且访问数组元素是时(即
array=null;
System.out.println(array[2]);
这两条代码时,就会产生如下所示结果:
(4) 如何处理异常?
第一步 :程序先执行 try 中的代码
第二步 :当 try 中的代码出现异常, 就会结束 try 中的代码, 同时,看和 catch 中的异常类型是否匹配
第三步 :找到匹配的异常类型, 就执行 catch 中对应的代码,没有找到与之匹配的异常类型, 就会将异常向上传递给上层调用者
第四步 :无论是否找到匹配的异常类型, finally 中的代码都会被执行到(在该方法结束之前执行)
最后 :一直到 main 方法也没有合适的代码处理异常, 就会交给 JVM 来进行处理, 此时程序才会终止异常
(5) finally 关键字
finally 执行的时机是在方法返回之前,但如果 finally 中存在 return 语句, 那么就会执行 finally 中的 return,而不会执行到 try 中原有的 return(建立在try-catch中也包含return语句),但 finally 都会执行
(6) Error
Error :指 Java 运行时内部出现错误 或 资源耗尽错误,应用程序不会抛出此类 异常,这种内部错误一旦出现,只能终止程序;
public class Test {
public static void method(){
method();
}
public static void main(String[] args) {
method();
}
}
类似于这种,函数自己调用自己,就会导致无限调用,此时就会抛出: 另一种错误:
int[] arr=new int[0x7fffffff];
4. 常见的异常
在之前的学习过程中,已经接触过了一些异常,常见的异常有:
除数为0(也叫算数异常 )
System.out.println(10/0);
结果会抛出:
数组下标越界(数组下标越界异常 )
int[] arr={1,2,3,4,5};
System.out.println(arr[6]);
结果会抛出:
访问 null 对象(空指针异常)
int[] arr=null;
System.out.println(arr[3]);
结果会抛出:
5. 防御式编程
程序出现问题的时候及时通知程序猿. 主要有两种主要的方式:
LBYL
Look Before You Leap,在操作之前做好充分的检查;
比如 :小时候喜欢吃辣条,当想吃的时候,就会问妈妈:“我可不可以吃一包辣条”征求妈妈同意后,再去吃!
EAFP
It’s Easier to Ask Forgiveness than Permission. “事后获取原谅比事前获取许可更容易”. 也就是 先操作, 遇到问题再处理(推荐使用 )
比如 :还是吃辣条,这次不一样了,直接先吃一包,于是,把妈妈气哭了,然后,开始安慰妈妈并道歉;
6. 自定义异常
- 自定义异常一定要继承一个父类异常,一般为
Exception 或 RuntimeException - 继承
Exception 的异常,称为受查异常 - 继承
RuntimeException 的异常,称为非受查异常
举例:
public class UserException extends RuntimeException{
public UserException(String message) {
super(message);
}
}
public class PasswordException extends RuntimeException{
public PasswordException(String message) {
super(message);
}
}
public class Login {
String name = "小明";
String password = "123456";
public boolean loginInfo(String n, String p) {
if (!name.equals(n)) {
throw new UserException("用户名输入错误");
}
if (!password.equals(p)) {
throw new PasswordException("密码输入有误");
}
return true;
}
public static void main(String[] args) {
Login login=new Login();
login.loginInfo("admin","123456");
}
}
输出结果: 不妨试一下:用户名输入正确时的情况 以及用户名和密码均正确时的情况;
|