目录
1.概念
2.异常的家族体系
3.异常的处理
3.1LBYL(事前防御型)
3.2EAFP(事后认错型)
4.异常的抛出
5.异常的捕获
5.1异常的声明
5.2异常的捕获
5.3finally
6.自定义异常类
在生活中我们也经常会感到异常,比如我们身体的某个地方疼,那指定是有什么地方做了不对的事情,对于计算机来说,也是这样,当你的程序运行的不对了,也是有一些做的不好的事情锁导致的.所以我们就能得到定义
让我们看一张图
在这张图中,我们可以发现很多我们在写程序的时候可能遇到过的异常
这里的Error是错误,我们先不说
比如:NullPointerException(空指针异常),ArrayIndexOutOfBoundsException(数组越界异常)等等
另一方面,我们也可以从图中看出来,所有的异常最终都是继承Throwable类的,而异常时继承Exception的,这个类又分成运行时异常和受查异常(IOException)和非受查异常(RuntimeException)
受查异常:又叫编译时异常,程序在编译的时候就会报错的异常,不能通过编译.例如我们前面说的clone接口,使用的时候需要处理异常,这种就是受查异常
非受查异常:又叫运行时异常,就是程序可以通过编译,但是执行的过程中出现的异常.例如数组越界,栈溢出
这个比较抽象,我们用一段伪代码来理解
boolean ret = false;
ret = 登陆程序();
if(!ret){
处理不登陆异常;
return;
}
ret = 运行聊天窗口();
if(!ret){
处理运行聊天异常;
return;
}
在这里我们可以看到,当我们哪一步出现异常的时候,我们在后面解决了异常,这样后面只要能执行,就没异常了,即使有,也会在里面处理了
但是我们可以看到,这个整个的逻辑比较混乱,冗余,所以我们引出第二种方法
先斩后奏总是更容易取得原谅,所以有了这种处理方法,在java中也提供了相关的语法try{}catch(){}
来和上面的伪代码对比
boolean ret = false;
try{
登陆失败;
运行失败;
}catch (登陆失败){
处理登陆失败异常;
}catch (运行失败){
处理运行失败;
}
}
这里和上面的区别就是这里的异常时先触发了,然后再catch中去处理异常,代码的可读性提高了
我们不仅可以让编译器抛异常,Java中是支持我们自己抛出异常的
public class Main {
public static void main(String[] args) {
int[] a = new int[10];
int i = 10;
if(i == 10){
throw new ArrayIndexOutOfBoundsException();
}
}
}
这里我们并没有去执行越界操作,只是给了一个i,然后如果i==10,我们直接手动抛出异常,得到的结果是这样的
这里我们用throws关键字,写在方法的后面,代码如下
public static void main(String[] args) throws CloneNotSupportedException
这样其实作用是这里并不处理异常,只是把异常声明出来,交给方法的调用者去处理,给出提醒
当调用者使用该方法时,必须进行处理,或者继续用throws进行声明
注意:.声明的异常必须是Exception类或者Exception的子类,如果抛出多个异常,再后面用','隔开就好了
这里先说一下try-catch的语法
try{可能出现异常的语句}
catch(捕获的异常类型 e){异常的处理}
这里的处理可以用这个方法进行对异常信息的打印e.printStackTrace();
这里捕获是从上到下依次捕获的,我们一次只能捕获一个异常,且try异常只会的语句将不会再被执行
这里是在try-catch语法后面的东西,这个所包裹的是必定执行的语句(无论是否异常),例如
public class Main {
public static void main(String[] args) {
try {
System.out.println(1);
}catch (Exception e){
}finally {
System.out.println("hahahaha");
}
}
}
我们得到的结果是这样的
这个不仅如此,当我们try和catch中同时又return语句的时候,甚至会返回finally中的return语句,我们验证一下
public class Main {
public static int demo(){
try {
return 1;
}catch (Exception e){
}finally {
return 2;
}
}
public static void main(String[] args) {
System.out.println(demo());
}
}
可见finally的优先级是特别高的,它一般用于扫尾工作,就是发生异常了,对一些资源的关闭
这里有一点容易忽略,如果我们没用捕捉到异常,异常就处理不了了?
不是这样的,如果我们没用人工捕获到异常,那么这个异常会交给到JVM中去处理
这个其实特别简单,直接看代码
//先定义一个类,然后继承Exception或者它的子类
class demoException extends RuntimeException{
//创建构造方法,并帮助父类构造
public demoException(String message){
super(message);
}
//这里又构建了一个无参的构造方法
public demoException(){
}
}
就这个语法,我们就成功的写出来了一个异常类
那你肯定想知道这里的messa是个什么玩意把
class demoException extends RuntimeException{
public demoException(String message){
super(message);
}
}
public class Main {
public static void main(String[] args) {
throw new demoException("哈哈哈哈");
}
}
看这段代码的执行结果是什么
可以看到,我们传入的message其实就是最后异常后面的提示符
异常其实并不难,只是一个新事务,我们慢慢去接受就好了
感谢阅读!!!