java异常

目录

(一)什么是异常

(1)定义

(2)体系结构

(二)异常处理

 (1)异常抛出

1.1Throw

1.2Throws

(2)异常捕获处理

2.1try-catch

 2.2异常处理流程

(三)自定义异常

(1)步骤


(一)什么是异常

(1)定义

Java 中,将程序执行过程中发生的 不正常行为 称为异常,如算术异常,空指针异常等...

(2)体系结构

如下图,Throwable是java异常体系中的顶层类,其派生出两个子类,Error和Exception
Error:是指jvm无法解决的严重问题,如栈溢出,堆溢出等...
Exception:是指 异常产生后 可以通过代码进行处理 ,使程序继续执行的异常情况,异常又分为受检查异常(编译时发生的异常)和非受查异常(运行时发生的异常)

(二)异常处理

异常处理五大关键字: throw、throws try、catch、final。

 (1)异常抛出

1.1Throw

在编写程序时,如果程序中出现错误,此时就需要将 错误的信息告知给调用者 ,可以借助 throw 关键字, 抛出 一个指定的异常对象,将错误信息告知给调用者。
注意点
1.throw 必须写在方法体内部(花括号内)
2. 抛出的对象必须是 Exception 或者 Exception 的子类对象
4. 如果抛出的是编译时异常(受查异常),用户必须处理,否则无法通过编译
5. 异常一旦抛出,其后的代码就不会执行

1.2Throws

当方法中抛出的是编译时异常(受检查异常),用户不想处理该异常,此时就可以借助 throws 将异常抛 给方法的调用者来处理。即 当前方法不处理异常,提醒方法的调用者处理异常。
(就是说假如我手上有个手机有问题,但我不想自己解决这个问题,我就用throws把这个问题抛出,交给想用这个手机的人去解决这个问题)
注意点
1. throws 必须跟在方法的参数列表之后
2. 声明的异常必须是 Exception 或者 Exception 的子类
3. 方法内部如果抛出了多个异常, throws 之后必须跟多个异常类型,之间用逗号隔开,如果抛出多个异常类型 具有父子关系,直接声明父类即可。
下代码为method1方法不想处理IOException(受查异常)使用throws抛出,主方法调用时,使用的是try ——catch方法进行处理(修手机),另外主方法也可以选择继续将异常抛出(继续将问题手机传给下一个人)

import java.io.IOException;

class Mehod{

public void  method1() throws IOException {//我不想处理这个编译时异常,就用throws把异常抛出
    int a = 10;
    if (a == 10){//定义如果变量a的值为10则抛出编译时异常
        throw new IOException("抛出了编译时异常");//不抛出会报错
    }
}
}
}


public class Main {
    public static void main(String[] args) {
        Mehod mehod = new Mehod();
        try {
            mehod.method1();//不处理会报错,这里选择try catch处理
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

下图为主方法选择throws继续抛出异常处理,但其实下方代码并不合理,这是因为main方法是程序的入口点,它的执行终止意味着整个Java应用程序的结束,所以在main方法一般是不能用throws抛出异常的

(2)异常捕获处理

2.1try-catch

try:   try中放的是可能会出现异常的代码

catch: 如果try中的代码抛出异常了,catch捕获时异常类型与try中抛出的异常类型一致时,或者catch捕获时异常是try中抛出异常的父类时,就会被捕获到,然后对异常进行处理,处理完成后,跳出try-catch结构,继续执行后序代码

下方代码是try-catch的具体语法规范

public class Main {
    public static void main(String[] args){//选择继续抛出异常
        Thread t = new Thread(()->{
            try {//try中放的是可能会发生异常的代码
                Thread.sleep(1000);
            } catch (InterruptedException e) {//catch括号中用于捕获抛出的异常
                //方法体中是对异常进行处理的代码
                e.printStackTrace();
            }
        });
    }
}

 注意点

1. try 块内抛出异常位置 之后的代码 将不会被执行
2. 如果抛出异常类型与 catch(捕获) 时异常 类型不匹配 ,即异常 不会被成功捕获 ,也就不会被处理,继续往外抛,直到 JVM收到后中断程序。
3. try 中可能会抛出多个不同的异常对象,则必须用多个 catch 来捕获
4.如果异常之间具有父子关系,一定是子类异常在前 catch ,父类异常在后 catch(父类在前catch的话异常都被父类捕获完了,就没子类什么事了)

2.2finally

有些 特定的代码 ,不论程序是否发生异常,都 必须要执行 ,比如程序中资源的关闭 :网络连接、数据库 连接、IO 流等, 在程序正常或者异常退出时,必须要对资源进进行回收 。另外,因为 异常会引发程序的跳转,可能 导致 有些语句执行不到 finally 就是用来解决这个问题的,因为在finally中的代码无论是异常还是正常,都会被执行到。
如下图try中的代码抛出的算术异常没有被catch正确捕获,后面的打印操作不会被执行到,但finally中的代码,一定会被执行到,所以 一般是在finally中执行比较重要的资源管理工作
public class Main {
    public static void main(String[] args){//选择继续抛出异常
        Mehod mehod = new Mehod();
        try {
            int a = 10/0;//抛出的是算术异常
        } catch (ClassCastException e) {
            e.printStackTrace();
        }finally {
            System.out.println("一定会被执行到");
        }
        System.out.println("此处异常没被正常处理不会执行到");
    }
}
注意点
1.finally 执行的时机是在 方法返回之前 (try 或者 catch 中如果有 return 会在这个 return 之前执行finally). 但是 如果 finally 中也存在 return 语句 , 那么就会执行 finally 中的 return, 从而 就不会执行到 try 中原有的 return, 所以一般不会在finally中使用return.
2.一般情况下只要不出现极端情况(jvm崩溃,操作系统错误等)finally块中的代码就一定会被执行到。

 2.2异常处理流程

1.程序先执行 try 中的代码
2.如果 try 中的代码出现异常 , 就会结束 try 中的代码 , 看和 catch 中的异常类型是否匹配 .
3.如果找到匹配的异常类型 , 就会执行 catch 中的代码
4.如果没有找到匹配的异常类型 , 就会将异常向上传递到上层调用者 .
5.无论是否找到匹配的异常类型 , finally 中的代码都会被执行到 ( 在该方法结束之前执行 ).
6.如果上层调用者也没有处理的了异常 , 就继续向上传递, 一直到 main 方法也没有合适的代码处理异常 , 就会交给 JVM 来进行处理 , 此时程序就会异常终止 .

方法之间是存在相互调用关系的 ,   JVM 中有一块内存空间称为 "虚拟机栈 " 专门存储方法之间的调用关系 . 当代码中出现异常的时候 , 我们就可以使用 e.printStackTrace(); 的 方式查看出现异常代码的调用栈.
如下图中从下向上看,可发现是main方法调用的method1方法

(三)自定义异常

有时候根据需要,我们也可以自定义一些异常类

(1)步骤

1. 自定义异常类,然后继承自 Exception 或者 RunTimeException
2. 实现一个带有 String 类型参数的构造方法,参数含义:出现异常的原因
如下图是定义一个自定义异常的语法,及使用

class MyException extends RuntimeException {//自定义一个运行时异常
    public MyException(String message) {
        super(message);

    }
}

public class Main {
    public static void main(String[] args) {//选择继续抛出异常
        int a =10;
         if (a == 10){
             throw new MyException("老皇甫自己的异常");
         }

    }
}

注意点

1.自定义异常通常会继承自 Exception 或者 RuntimeException
2.继承自 Exception 的异常默认是受查异常
3.继承自 RuntimeException 的异常默认是非受查异常

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值