当前位置: 首页 > article >正文

快速掌握异常(含面试题)

目录

  • * 异常的体系结构
  • 1. 异常的分类
      • 1.1 运行时异常
      • 1.2 编译时异常
  • 2. 异常的处理(含面试题)
      • 2.1 防御式编程
            • 1. 事前防御型---LBYL
            • 2. 事后认错型---EAFP
      • 2.2 抛出异常
      • 2.3 捕获异常---真正开始处理异常
      • 3.4 finally --- 回收资源
  • 3. 自定义异常类

在Java中,将程序运行中不正常的行为称为异常,比如经常遇到的数组越界异常。Java中不同类型的异常都有与其对应的类来描述。

异常一旦抛出,后边的代码不会再执行。

* 异常的体系结构

由于异常过于多,为了方便分类,Java内部维护了一个异常体系结构,如下(只展示一小部分)
在这里插入图片描述

  1. Throwable:是异常体系的顶层类,其派生出了两个类,Error和Exception。
  2. Error:是JVM无法解决的问题, 如JVM资源耗尽等, 如StackOverflowError(栈溢出错误)。
  3. Exception:是程序员能用代码处理的问题,如NullPointerException(空指针异常)。
    我们主要学习的是Exception类。

1. 异常的分类

Exception类分为运行时异常(非受查异常)和编译时异常(受查异常)。

1.1 运行时异常

运行时异常能通过编译,只在运行时JVM才会抛异常。
在这里插入图片描述

1.2 编译时异常

编译时异常不能通过编译,编写时就会抛出异常。注意区分语法错误和变异时异常

自己写的类想实现克隆,实现了Cloneable接口且重写了toString方法和clone方法,在main方法中克隆时依然抛出了异常
在这里插入图片描述

那出现了异常怎么解决?下面学习异常的处理。

2. 异常的处理(含面试题)

2.1 防御式编程

1. 事前防御型—LBYL

操作之前就进行检查。基本不用

boolean ret = false;
ret = 登陆游戏();
if (!ret) {
处理登陆游戏错误;
return;
}
ret = 开始匹配();
if (!ret) {
处理匹配错误;
return;
}
...
2. 事后认错型—EAFP

先操作,遇到问题再处理。处理异常的经典做法就是EAFP。

//方式一
try{
	存放可能有异常的代码
}catch (捕获某个的异常类) {
	
}
...
//方式二
try{
	存放可能有异常的代码
}catch (捕获某个的异常类 | 捕获某个的异常类 | ...) {
	
}

注:

  1. 可以用多个catch捕获多个异常,该语句能让程序员自己处理异常,而不是交给JVM。
  2. 虽然可以捕获多种异常,但同一时刻只能捕获一个异常。
  3. catch不能用父类(Exception)接收所有的异常子类,但可以先catch子类,父类作最后一个catch,作垫背。
  4. try()内部可以加Scanner等语句

2.2 抛出异常

抛出异常有两种方式:由程序触发/通过throw关键字手动抛出

手动抛出异常的语法:throw new XXXException(“异常产生的原因”);

try{
	int a = 10/0;
}catch (ArithmeticException e){
    e.printStackTrace();//打印错误信息在第几行
    throw new ArithmeticException("算数异常");
}
//运行结果 --- 抛异常
Exception in thread "main" java.lang.ArithmeticException: 算数异常
	at MyException.main(MyException.java:25)

注:

  1. throw必须在方法内部。
  2. 抛出的对象必须是Exception或Exception子类。
  3. 如果抛出的是运行时异常(RunTimeException)或RunTimeException的子类,不需要处理,直接交给JVM处理即可。
  4. 若抛出的是编译时异常,必须处理,否则无法通过编译。

2.3 捕获异常—真正开始处理异常

处理异常有两种方式,

  1. 声明异常,用throws关键字,在方法声明后面抛出异常(告诉方法调用者,调用该方法会抛出某个异常),但这个异常是交给JVM处理的。
public static void main(String[] args) throws CloneNotSupportedException {
        MyExc myExc = new MyExc("Bob");
        MyExc myExc1 = (MyExc)myExc.clone();
        System.out.println(myExc1);
}
  1. 手动抛出异常,throw关键字,抛出的一般是自定义的异常,该异常由程序员自己处理。
public static void main(String[] args) {
        try{
            int a = 10/0;
        }catch (ArithmeticException e){
            e.printStackTrace();
            throw new ArithmeticException("算数异常");
        }
}

3.4 finally — 回收资源

不论程序是否发生异常,finally中的语句一定会被执行。比如打开文件,如果抛出异常会执行不到关闭文件的代码,但必须对资源进行回收,这时放在finally内部,就能关闭文件。

finally一般在return语句之前执行,finally内不要有return语句。不然会执行其内部的return语句,执行不了try语句的return。如下,
想要得到10,进入try语句,进入finally语句,直接return20,没有执行try中的return10。

public static int func() {
	try {
		return 10;
	} finally {
		return 20;
	}
}

若没有catch异常,异常抛出,后面的代码不会执行(main不会打印),但finally内的语句依旧打印

public static void main(String[] args) {
        try(Scanner scanner = new Scanner(System.in)) {
        	//存放可能出现异常的代码
            int a = scanner.nextInt();
            int b = a/0;
        }finally {
        	//不论程序是否发生异常,语句一定会被执行
            System.out.println("finally");
        }
        //异常若被捕或没有异常,语句会被执行
        System.out.println("main");
    }
    
//运行结果
finally
Exception in thread "main" java.lang.ArithmeticException: / by zero
	at MyException.main(MyException.java:26)

【面试题】:

  1. throw 和 throws 的区别?

  2. finally中的语句一定会执行吗?

3. 自定义异常类

自定义异常类必须继承Exception类(受查异常)或者RunTimeException(非受查异常)。示例如下,
我想抛出用户名异常和密码异常,库中没有,就需要自己写。两个异常要继承Exception类或RunTimeException类。并在throw所在的方法内throws(声明异常),在main方法中处理异常。

class userException extends Exception {

    public userException(String message) {
        super(message);
    }
}
class passwordException extends RuntimeException{

    public passwordException(String message) {
        super(message);
    }
}

public class LogIn {

    private String userName = "admin";
    private String password = "123456";

    public static void loginInfo(String userName, String password) throws userException,passwordException{
        if (!userName.equals(userName)) {
            throw new userException("用户名错误");
        }
        if (!password.equals(password)) {
            throw new passwordException("密码异常");
        }
        System.out.println("登陆成功");
    }
    public static void main(String[] args) {
        try{
            loginInfo("admin", "123456");
        }catch (userException e){

        }catch (passwordException e){

        }

    }
}

http://www.kler.cn/a/513483.html

相关文章:

  • E-Prime2实现List嵌套
  • ESP32下FreeRTOS实时操作系统使用
  • 光谱相机在智能冰箱的应用原理与优势
  • Linux容器(初学了解)
  • 大数据学习(37)- Flink运行时架构
  • SpringCloud nacos 2.0.0 + seata 2.0.0
  • Linux 更换yum镜像源
  • 小米平板pad6工程固件界面预览 修复tee损坏 修复底层分区 开diag端口
  • Apache Tomcat文件包含漏洞复现(详细教程)
  • C语言小任务——1000以内含有9的数字
  • 第3章 存储系统
  • 偏序关系.
  • LeetCode hot 力扣热题100 翻转二叉树
  • 最新百应abogus纯算还原流程分析
  • WPF2-1在xaml为对象的属性赋值.md
  • DOL-288 多功能电子计时器说明书
  • (10)深入浅出智能合约OpenZeppelin开源框架
  • Linux内核编程(二十一)USB驱动开发-键盘驱动
  • es 3期 第25节-运用Rollup减少数据存储
  • VINS-Mono源码阅读(一)程序简介、编译调试、配置文件
  • Unity自学之旅04
  • 缓存系统(redis)测试体系
  • 智慧脚下生根,智能井盖监测终端引领城市安全新革命
  • Mybatis 进阶 / Mybatis—Puls (详细)
  • 升级《在线写python》小程序的分享功能。昨天忘了...
  • Keil5 IDE使用笔记