Java知识点——异常机制

写在前面: 查阅「Java官方手册」(Java 11 官方API)和学习「Java源码」是学习这门语言的必经之路。

1 异常的基本概念

Java中的「异常」指程序执行中发生的不正常情况,常见的异常如下图所示:

在这里插入图片描述

以上的异常类都存在于java.lang包中,以上类的具体含义如下:

  • Throwable类:Java中Error和Exception的超类

  • Error类:描述Java虚拟机无法解决的严重错误,如,JVM挂掉的情况

  • Exception类:描述因编程错误或其他因素导致的轻微错误,可通过修改程序解决,如,以8为下标访问长度为7的数据,会发生ArrayIndexOutOfBoundsException异常

  • IOException类和其他异常:检测性异常,能够在编译阶段能被编译器识别的异常

  • RuntimeException类:非检测性异常,在运行阶段才能被识别的异常

  • 虚线框中的非检测性异常类:Java初学者常出现的5种异常

2 异常捕获

异常的捕获方法为:try{} catch {} ... finally{} ,具体写法参照注意点4中的代码。

注意点:

  1. 编写多个catch分支时,需要把小类型放在大类型前面

  2. catch (Exception e) {…} 可以直接捕获所有异常

  3. finally中的代码块是必执行的,比如打开文件后,可以把关闭文件的代码放在这个部分

  4. 虽然return是结束程序并返回,但是finally在结束程序前必须执行

针对注意点4,举个例子

阅读下述代码,请问打印的 i 等于几?

 public class ExceptionCatchTest {
 
     public static int finallyReturnExample() {
         try {
             for (int i = 0; i < 10; i++) {
                 System.out.println("i = " + (100 / i));
             }
             return 0;
         } catch (ArithmeticException e) {
             e.printStackTrace();
             return 1;
         } finally {
             return 2;
         }
     }
     
     public static void main(String[] args) {
 
         int i = ExceptionCatchTest.finallyReturnExample();
         System.out.println("i = " + i); 
     }
 }

注:不妨执行下上述代码,体会 i 是否等于你心里想的那个数~

3 异常的抛出

异常的抛出:有些异常在特殊情况无法或不方便处理,这时,可以将该异常转移给该方法的调用者。

语法格式如下:

访问权限 返回值类型 方法名称(形参列表) throws 异常类型1, 异常类型2, ... {
  方法体;
}
// 例如:
public void show() throws ArithmetictException {}

注意点:

  1. 子类重写父类的方法:不能抛出「更大的异常、平级但名称不一样的异常」,可以抛出「一样的异常、更小的异常」以及「不抛出异常」

  2. 建议不要在main方法中抛出异常,JVM的负担很重,到了main这一层采用就地解决(异常捕获)的方式

  3. 父类被重写的方法没有抛出异常、子类中重写的方法只能进行异常的捕获处理

  4. 若一个方法内部以递进的方式调用了很多其他的方法,建议在方法内使用抛出的方法处理到最后一层进行捕获处理

针对注意点4,举个例子:

   public class InnerThrowsTest {
     
       public static void show() throws IOException {
           // FileInputStream产生异常,直接抛出
         	FileInputStream fis = new FileInputStream("./a.txt");
           fis.close(); 
       }
       public static void test1() throws IOException {
           show(); // test1()调用show(), 异常抛出给test1()
       }
       public static void test2() throws IOException {
           test1(); // test2()调用test1(), 异常抛出给test2()
       }
   
       public static void main(String[] args) /*throws IOException*/ {
         	// 到main层就地处理,不再抛出
           try {
               test2();
           } catch (IOException e) {
               e.printStackTrace();
           }
       }
   }

4 自定义异常

当Java官方没提供「自己的项目」所需的针对性异常,则需要自定义描述这类异常。

编写流程

  • 自定义@@@Exception异常继承Exception类或其子类
  • 提供序列化版本号
  • 提供两个版本的构造方法:
    • 无参构造方法
    • 以字符串为参数的有参构造方法

异常的产生:throw new 异常类型(实参);

举个例子:

若要开发一个学生管理系统,存储学生信息时会涉及到如学号、年龄等需要进行异常值判定的成员变量,这里以学生年龄的为例,我们需要对不合理的年龄时产生异常对象并抛出,具体如下:

// 参考Exception类的源码进行设计自定义异常
public class AgeException extends Exception {

    static final long serialVersionUID = 7818375828146090155L; // 序列化的版本号
    
  	public AgeException() {
    } // 无参构造
    public AgeException(String message) {
        super(message);
    } // 有参构造,以字符串为参数
}

// 为了体现如何使用自定义异常,仅展示一个年龄成员变量的封装
public class Student {
    private int age;

    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        if(age >= 0 && age <= 150) {
            this.age = age;
        } else {
            try {
                throw new AgeException("输入的年龄不符合要求!");
            } catch (AgeException e) {
                e.printStackTrace();
            }
        }
    }
}

异常的处理总原则

  • 在开发中采用if条件判断尽量避免异常;
  • 避免不了则进行异常的捕获;
  • 捕获不了则进行异常的抛出;
  • 另外,可采用自定义异常来对针对性异常进行处理。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值