Java异常

一、概述

  在程序运行过程中出现的错误,称为异常。Java中,把各种异常现象进行了抽象形成了异常类。
异常处理的目的是为了提高程序的安全性与健壮性。

二、异常分类

在这里插入图片描述

异常都继承自Throwable类。
分为Error、Exception两大类:
1、Error(错误)
  此类错误通常为虚拟机相关错误,如系统崩溃,内存不足,堆栈溢出等。是程序无法处理的错误,非代码性错误,表示出现了严重的错误,一旦这类错误发生,通常应用程序会被终止,仅靠应用程序本身无法恢复;
2、Exception
  程序本身可以捕获并且可以处理的异常。
该类异常又分为两大类:

  • 运行时异常(不受检查异常):是RuntimeException类及其子类表示的异常,指的是JVM在运行期间可能出现的错误。

特点:

♦此类异常编译器不会去检查,所以也称不受检查异常;
♦此类异常一般由程序逻辑错误引起的,可以捕获处理,也可以不处理

  • 编译时异常(受检查异常):Exception中除RuntimeException极其子类之外的异常。

特点:

♦编译器会检查此类异常,所以也称受检查异常;
♦出现此类异常时,必须要处理,否则编译不通过;

三、Java常见异常有哪些

常见的运行时异常:

  • NullPointerException:空指针异常,调用了未经初始化的对象或者是不存在的对象;
  • ClassCastException:类型转换异常;
  • IllegalArgumentException:非法的参数异常;
  • IndexOutOfBoundsException:数组下标越界异常;
  • ArithmeticException:算术异常;
  • SQLException:SQL异常;

常见的非运行时异常:

  • IOException:IO流异常;
  • ClassNotFoundException:没找到指定类异常;
  • NoSuchFieldException:没找到指定字段异常;
  • NoSuchMetodException:没找到指定方法异常;
  • InterruptedException:中断异常;

四、异常的处理

运行时异常不需要预处理,通过规范的代码可以避免产生这种异常;
而编译时异常必须预处理,否则编译报错,有两种预处理方式 :捕获处理抛出处理

Ⅰ、异常捕获处理

在代码中使用trycatchfinally将异常捕获
格式1

        try {
         //写可能产生异常的代码
         
        } catch (异常类型1 e1) {
         //捕获异常类型1的异常, 进行处理
         
        } catch (异常类型2 e1) {
         //捕获异常类型2的异常, 进行处理
         
        } finally {
         //一般情况下, 这里写释放系统资源的语句
         
        }

注意点:

  • 如果try代码块的某条语句产生了异常, 就立即跳转到相应catch子句执行, try代码块该语句后面的代码不再执行
  • try块里可能会产生多个异常,所以后面的catch可以有多个,以捕获多种异常
  • 在开发时, 异常的处理方式一般是打印异常栈跟踪信息(e.printStackTrace())
  • 在部署后, 一般是把异常信息打印到日志文件中(logger.error(e.getMessage()))
  • 如果捕获的异常类型有继承关系, 应该先捕获子异常再捕获父异常,如果没有继承关系, catch子句没有先后顺序
  • 若try里面有return,则先运行finally里的语句再执行return
  • 正常来说finally里的语句都会执行,但以下情况不会
  • 若try里面有System.exit(0)强制退出,则不会运行finally块
  • 如果在进入try块之前就出现异常,则也不会运行finally块

格式2:

        try (/*资源变量的声明、赋值*/){
           //数据操作
           
        } catch (异常类型 e) {
           //捕获异常并处理
           
        }

  在1.7 JDK后,java提供了try–with–resource语法糖,资源对象需要实现AutoCloseable接口(几乎所有资源类都实现了该接口),重写其中的close方法,那么在try()里打开资源,相关资源就会自动关闭,不再需要手动执行,不管是正常退出或异常退出,这意味着可以不用在finally块中关闭资源;
示例:

        File file = new File("file1.txt");
        try (FileInputStream in =new FileInputStream(file)){
            byte[] b=new byte[1024];
            int length=0;
            while((length=in.read(b))!=-1){
                System.out.println(new String(b,0,length));
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
Ⅱ、异常抛出处理

在方法声明中使用throws抛出异常
格式:

public void method( ) throws 异常1,异常2{
//方法体
}

注意点:

  • 抛出该异常的方法不处理异常,而是谁调用这个方法,谁负责处理该异常
  • catch块中通过throw语句抛出了一个异常,所在的方法应该使用throws抛出该异常

  若最终在main方法上抛出异常,JVM 就会将该异常转交给默认的异常处理器(默认处理器为 JVM 的一部分),默认异常处理器打印出异常信息并终止应用程序

Ⅲ、如何选择处理异常的方式

  一般情况下,如果方法体中有编译时异常需要预处理,可以选择捕获 ,也可以选择抛出处理。
  在调用其他方法时,如果被调用的方法有抛出编译时异常时,选择捕获处理,因为你调用了方法, 你负责处理该异常。

Ⅳ、异常处理相关方法
  • String getMessage():获取异常描述信息
  • void printStackTrace():获取异常的跟踪栈信息
Ⅴ、throw 和 throws 的区别

throw

  • 用在方法内部,表示抛出一个异常实例
  • 只能用于抛出一种异常,throw一般用于抛出自定义异常。

throws

  • 用在方法声明上,表示可能会发生这几种异常
  • 可以抛出多种异常;

五、自定义异常

自定义异常通常继承于ExceptionRuntimeException
自定义异常类可以有自己的变量方法传递异常相关信息

定义异常类

//运行时异常
class myRuntimeException extends RuntimeException{
    public myRuntimeException(String message){//构造函数,其中参数message为异常对象的描述信息
        super(message);
    }
}
//编译时异常
class myCheckedException extends Exception{
    public myCheckedException(String message){
        super(message);
    }
}

使用

class myThrowTest{
    public static int divide1(Integer x, Integer y){
        if(y==0){
            throw new myRuntimeException("除数y不能为0!");//抛出自定义的运行时异常
        }else {
            return x/y;
        }
    }
    public static int divide2(Integer x, Integer y) throws myCheckedException {
        if(x==null||y==null){
            throw new myCheckedException("数据为空!");//抛出自定义的编译时异常
        }else {
            return x/y;
        }
    }

    public static void count1(Integer x,Integer y){
        try {
            x=2;y=0;
            int result=divide1(x,y);
            System.out.println(result);
        } catch (myRuntimeException e) {//可能会出现myRuntimeException 异常,可以处理,也可以不处理
            e.printStackTrace();
        }
    }

    public static void count2(Integer x,Integer y){
        try {
            int result=divide2(x,y);
            System.out.println(result);
        } catch (myCheckedException e) {//检测出myCheckedException 异常,必须要处理
            e.printStackTrace();
        }
    }
    public static void main(String[] args){
        Integer x=null;
        Integer y=null;
        count1(x,y);
        count2(x,y);
    }
}

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值