JavaSE 之认识异常

目录

  1. 异常的概念
  2. 异常的处理方式
  3. 异常的处理流程
  4. 自定义异常类

1.1 异常的概念

在 Java 中,将程序执行过程中发生的不正常行为称为异常。

比如我们以前写代码遇到的:

  1. 算术异常
  2. 数组越界异常
  3. 空指针异常

 不同的异常都有不同的类来描述。

1.2 异常的体系结构

异常种类繁多,为了对不同异常或者错误进行很好的分类管理,Java 内部维护了一个异常的体系结构:

1. Throwable:是异常体系的顶层类,其派生出两个重要的子类, Error 和 Exception

2. Error(错误):指的是 Java 虚拟机无法解决的严重问题,比如:JVM 的内部错误、资源耗尽等。典型代表:StackOverflowError(栈溢出)和 OutOfMemoryError,一旦发生回力乏术。

3. Exception:异常产生后程序员可以通过代码进行处理,使程序继续执行,上面举的例子都是异常。

1.3 异常的分类

1.运行时异常

程序执行时发生的异常称为运行时异常,也称为非受查异常。

2.编译时异常

程序编译期间发生的异常叫做编译时异常,也称为受检查异常。

比如我们创建一个类,new一个对象,然后克隆这个对象:


我们发现重写的克隆方法的返回类型是 object,那我们强转一下:

还是报错,我们在 main 方法后面声明异常就行了。

 编译时的异常编译期间一定要处理,否则编译不能通过。

2.1 异常的处理

try{
//可能出现异常的代码

}catch(捕获具体的异常){


}finally{

}

这样的优势是:正常流程和错误流程是分开的,代码更清晰,容易理解代码。

在Java中,异常处理主要的5个关键字:throw, try, catch, finally, throws

2.2 异常的抛出

在 Java 中,可以借助 throw 关键字,抛出一个指定的异常对象,将错误信息告知给调用者。

举例:

这是我们手动抛出的异常。 

注意事项:

  1. throw必须写在方法体内部。
  2. 抛出的对象必须是 Exception 或 Exception 的子类对象。
  3. 如果抛出的是 RunTimeException 或者 RunTimeException 的子类,则可以不用处理,交给JVM来处理。
  4. 如果抛出的是编译时异常,则用户必须处理,否则无法通过编译。
  5. 异常一旦抛出,其后的代码就不会执行

2.3 异常的捕获

异常的捕获,也就是异常的具体处理方式,主要有两种:异常声明 throws 以及 try-catch 捕获处

理。

1.异常的声明 throws

这个关键字使用在方法的声明之后,告诉方法的调用者,使用这个方法会抛出 xxx 异常。

为什么刚刚克隆的例子加上这个就不报错了呢??

如果一个方法内部存在编译时异常,此时这个编译时异常一定要处理,

目前我们处理的方式是:在方法定义的时候,通过 throws 关键字抛出异常,最后交给 JVM 处理。

注意:

  1. throws 必须跟在方法的参数列表之后
  2.  声明的异常必须是 Exception 或者 Exception 的子类
  3. 方法内部如果抛出了多个异常,throws 之后必须跟多个异常类型,之间用逗号隔开,如果抛出多个异常类型具有父子关系,直接声明父类即可
  4. 调用声明抛出异常的方法时,调用者必须对该异常进行处理,或者继续使用 throws 抛出。

2. try-catch 捕获并处理

如果不想把异常交给 JVM 处理,想要自己处理,就需要 try-catch .

使用 try-catch 自己处理:

关于异常的处理方式:

异常的种类有很多, 我们要根据不同的业务场景来决定,

  1. 对于比较严重的问题(例如和算钱相关的场景), 应该让程序直接崩溃, 防止造成更严重的后果
  2. 对于不太严重的问题(大多数场景), 可以记录错误日志, 并通过监控报警程序及时通知程序猿
  3. 对于可能会恢复的问题(和网络相关的场景), 可以尝试进行重试.

注意事项:

1. try块内抛出异常位置之后的代码将不会被执行。

2. 如果抛出异常类型与catch时异常类型不匹配,即异常不会被成功捕获,也就不会被处理,继续往外抛,直到JVM收到后中断程序----异常是按照类型来捕获的。

3. try中可能会抛出多个不同的异常对象,则必须用多个catch来捕获----即多种异常,多次捕获。

同一时刻只能抛出一个异常!!

如果异常之间具有父子关系,一定是子类异常在前,父类异常在后,否则语法错误!

不能用父类异常接收所有异常,因为此时异常不精准。

3. finally

在异常处理中,如释放资源,关闭数据库、关闭文件应由 finally 语句来完成。

 

finally 的语句一定会被执行!一般在 finally 中进行一些资源清理的扫尾工作。

不建议在 finally 中写 return (被编译器当做一个警告).

3. 异常处理的流程

程序先执行 try 中的代码。

如果 try 中的代码出现异常就会结束 try 中的代码,看和 catch 中的异常类型是否匹配。

如果找到匹配的异常类型, 就会执行 catch 中的代码。

如果没有找到匹配的异常类型, 就会将异常向上传递到上层调用者。

无论是否找到匹配的异常类型, finally 中的代码都会被执行到(在该方法结束之前执行)。

如果上层调用者也没有处理的了异常, 就继续向上传递。

一直到 main 方法也没有合适的代码处理异常, 就会交给 JVM 来进行处理, 此时程序就会异常终止

4.自定义异常类

class PassWordException extends Exception{
    public PassWordException(String message){
        super(message);
    }
}
public class Test2 {

    private String userName = "admin";
    private String passWord = "12345";
    public static void loginInfo(String userName, String passWord) throws UserNameException,PassWordException {
        if(!userName.equals(userName)){
            throw new UserNameException("用户名错误!");
        }
        if(!passWord.equals(passWord)){
            throw new PassWordException("密码错误!");
        }
        System.out.println("登录成功!");
    }

    public static void main(String[] args) {
        try{
            loginInfo("admin","12345");
        }catch(UserNameException e){
            e.printStackTrace();
        }catch(PassWordException e){
            e.printStackTrace();
        }
    }
}
  1. 自定义异常通常会继承自 Exception 或者 RuntimeException
  2. 继承自 Exception 的异常默认是受查异常
  3. 继承自 RuntimeException 的异常默认是非受查异常


 

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值