Java异常机制

Java异常机制

什么是异常

  • 软件程序在运行过程中,遇到的一些不期而至的状况,阻止了程序的运行。如:文件找不到、网络连接失败、非法参数等,影响了正常的执行流程。这种叫做异常,英文是 Exception。

异常体系结构

  • Java把异常当做对象来处理,并定义了一个基类java.lang.Throwable作为异常的超类。
  • Java API 中已经定义了许多异常类,这些异常类分为两大类,错误Error 和 异常Exception
    在这里插入图片描述

Error

  • Error类对象由Java虚拟机生成并抛出,大多数错误与代码编写者所执行的操作无关。
  • Java虚拟机运行错误(Virtual MachineError),当JVM不再有继续执行操作所需的内存资源时,将出现OutOfMemoryError。这些异常发生是,Java虚拟机(JVM)一般会选择线程终止(较为严重)
  • 在虚拟机试图执行应用时,如类定义错误(NoClassDefFoundError)、链接错误(LinkageError)。这些错误都是不可查的,因为它们在程序的控制和处理能力之外,而且绝大多数是程序运行时不允许出现的状况。

Exception

  • 在Exception分支中有一个重要的子类 RuntimeException(运行时异常)。
    • 数组下标越界(ArrayIndexOutOfBoundsException)。
    • 空指针异常(NullPointerException)。
    • 算术异常(ArithmeticException)。
    • 丢失资源(MissingResourceException)。
    • 找不到类(ClassNotFoundException)等异常。

这些异常一般是由程序逻辑错误引起的,程序应该从逻辑角度尽可能避免这类异常的发生。

异常分类

检查性异常

​ 所谓检查是指 编译器 要检查这类异常,检查的目的一方面是因为该类异常的发生难以避免,另一方面是让开发者去解决掉这类异常,所以称为必须处理(try…catch)的异常。如果不处理这类异常**,集成开发环境中的编译器一般会给出错误提示**。最具代表的检查性异常是用户错误或问题 引起的异常,这种程序员无法预见的。这些异常在编译时不能被简单的忽略。

​ 常见的检查性异常:输入输出异常(IOException)、文件不存在异常(FileNotFoundException)、SQL语句异常(SQLException)等。

运行时异常

​ 运行时异常是可能被程序员避免的异常。与检查性异常相反,运行时异常可以在编译时被忽略,这类错误是程序员可以避免的,编译器不会强制检查这种异常

​ 常见的运行时异常:空指针异常(NullPointerException)、除零异常(ArithmeticException)等。

错误
错误不是异常,而是脱离程序员控制的问题。在编译中检查不到。

Java异常处理机制

  • Java提供了更加优秀的解决方法:Java异常处理机制

    ​ 异常处理机制能让程序在异常发生时**,按照代码预先设定的 异常处理逻辑,针对性的处理异常,让程序尽最大可能恢复正常并继续执行,且保持代码的清晰**。

    ​ Java中的异常可以是函数中语句执行时引发的,也可以是程序员通过throw语句手动抛出的,只要在Java程序中产生了异常,就会用一个对应类型的异常对象来封装异常,JRE(Java运行环境)就会试图寻找异常处理程序来处理异常。

  • Java异常机制用到的几个关键字:try、catch、finally、throw、throws

    • try :**用于监听。**将要被监听的代码(可能抛出异常的代码)放在try语句块之内,当try语句块内发生异常时,异常就被抛出。
    • catch:**用于捕获异常。**catch用来捕获try语句块中发生的异常。
    • finally: **finally语句块总是会被执行。**主要用于回收在try语句块中打开的资源(数据库连接、网络连接、磁盘文件)。在finally执行完成以后,才会回来执行try或者catch中的return或者throw语句,如果finally中使用了return或者throw等终止方法的语句,则不会跳回执行,直接停止。
    • throw用于抛出异常。
    • throws用于声明该方法可能抛出的异常。主方法上也可以使用throws抛出。如果在主方法上使用了throws抛出,就表示在主方法里面可以不用强制性进行异常处理,如果出现了异常,就交给JVM进行默认处理,则此时会导致程序中断执行。

处理异常

  • 异常类型

    Error : JVM错误。

    Exception : 程序运行中可能出现的异常。

    Throwable : Error 和 Exception。

(1)try-catch语句

try{
	可能发生异常的语句;
}catch(异常类型 异常名(变量)){
    针对异常进行处理的代码;
}

(2)try-catch-finally语句

try{
	可能发生异常的语句;
}catch(异常类型 异常名(变量)){
    针对异常进行处理的代码;
}finally{
    释放资源的代码;
}

(3)try-catch-catch-(…)-finally语句

try{
	可能发生异常的语句;
}catch(异常类型 异常名(变量)){
    针对异常进行处理的代码;
}catch(异常类型 异常名(变量)){
    针对异常进行处理的代码;
}catch(异常类型 异常名(变量)){
    针对异常进行处理的代码;
}finally{
    释放资源的代码;
}

(4)throw

  • throw抛出异常的代码格式

    throw ExceptionObject;
    
  • 代码演示:

package com.Hrstudy.exception;

public class demo02 {
    public static void main(String[] args) {
        new demo02().test(1,0);
    }

    public void test(int a,int b){
        if(b==0){
            throw new ArithmeticException(); //主动抛出异常,一般在方法中使用
        }
    }

}
  • 运行结果:
    在这里插入图片描述

(5)throws

  • throws代码格式:

    returnType method_name(paramList) throws Exception 1,Exception 2…{…}

    returnType 表示返回值类型,method_name表示方法名,paramList表示参数列表;Exception 1、Exception 2表示异常类。

  • 使用throws声明抛出异常的思路是:当前方法不知道如何处理这种类型的异常,该异常应该由上一级的调用者处理;如果main方法也不知道如何处理这种类型的异常,也可以使用throws声明抛出异常,该异常会交给JVM处理。JVM对异常的处理方法是,打印异常的追踪栈信息,并中止程序运行,这就是前面程序在遇到异常后自动结束的原因。

  • 如果有多个异常类,它们之间用逗号分割。这些异常类可以是方法中调用了可能抛出异常的方法而产生的异常,也可以是方法体中生成并抛出的异常

  • 代码演示:

package com.Hrstudy.exception;

public class demo03 {
    public static void main(String[] args) {
        //快捷键 ctrl+alt+t try-catch
        try {
            new demo03().test(1,0);
        } catch (ArithmeticException e) {
            e.printStackTrace();
        }

        new demo03().test(1,0);

    }

    public void test(int a,int b) throws ArithmeticException{
        //向上抛出异常
    }
}
  • throw 和 throws 关键字的区分
    • throws用来声明一个方法可能抛出的所有的异常信息,表示出现异常的一种可能性,但并不一定会发生这些异常;throw是指抛出的一个具体的异常类型,执行throw则一定抛出了某种异常对象。
    • 通常在一个方法(类)的声明处通过throws声明方法(类)可能抛出的异常信息,而在方法(类)内部通过throw声明一个具体的异常信息。
    • throws通常不用显示的捕获异常,可由系统自动将所有捕获的异常信息抛给上级方法;throw则需要用户自己捕获相关的异常,而后对其进行相关包装,最后将包装就的异常信息抛出。

自定义异常

  • 使用Java内置的异常类可以描述在编程时出现的大部分异常情况。除此之外,用户还可以自定义异常,只需继承Exception类即可。

  • 在程序中使用自定义异常类,大体可分为以下几个步骤

    • 创建自定义异常类。
    • 在方法中通过throw关键字抛出异常对象。
    • 如果在当前抛出异常的方法中处理异常,可以使用try-catch语句捕获并处理;否则在方法的声明处通过throws关键字指明要抛出给方法调用者的异常,继续进行下一步操作。
    • 在出现异常方法的调用者中捕获并处理异常。
  • 代码演示

    创建自定义异常类

    package com.Hrstudy.exception.customException;
    //自定义的异常类 继承Exception
    public class MyException extends Exception{
        //传递数字>10报出异常
        private int detail;
    	//构造方法
        public MyException(int a) {
            this.detail = a;
        }
    
        //toString:异常的打印信息
        @Override
        public String toString() {
            return "MyException{" +
                    "detail=" + detail +
                    '}';
        }
    }
    

    测试类

    package com.Hrstudy.exception.customException;
    //自定义异常测试类
    public class Test {
        //可能会存在异常的方法
        //向上抛出,让上一级来捕获异常
        static void  test(int a) throws MyException {
            System.out.println("传递的参数为:"+a);
    
            if(a > 10){
                throw new MyException(a);//抛出异常
            }
    
            //程序正常运行
            System.out.println("OK");
        }
        //测试
        public static void main(String[] args) {
            try {
                test(12);//分别输入了两个参数 2  12
            } catch (MyException e) {//捕获异常
              //e.printStackTrace();
                System.out.println("MyException=>"+e);
            }
        }
    }
    

运行结果:

在这里插入图片描述
在这里插入图片描述

总结

实际应用中的经验总结

  • 处理运行时异常时,采用逻辑去合理规避同时辅助 try-catch 处理。
  • 在多重 catch 块后面,可以加一个catch(Exception)来处理可能会被遗漏的异常。
  • 对于不确定的代码,也可以加上一个 try-catch ,处理潜在的异常。
  • 尽量去写一些代码处理异常,切记只是简单的调用 printStackTrace()去打印输出。
  • 具体如何处理异常,要根据不同的业务需求和异常类型去决定。
    20705173929190" style=“zoom: 80%;” />

总结

实际应用中的经验总结

  • 处理运行时异常时,采用逻辑去合理规避同时辅助 try-catch 处理。
  • 在多重 catch 块后面,可以加一个catch(Exception)来处理可能会被遗漏的异常。
  • 对于不确定的代码,也可以加上一个 try-catch ,处理潜在的异常。
  • 尽量去写一些代码处理异常,切记只是简单的调用 printStackTrace()去打印输出。
  • 具体如何处理异常,要根据不同的业务需求和异常类型去决定。
  • 尽量添加finally语句块去释放占用的资源。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值