java之异常处理

异常概述

  • Java应用程序外部环境和内部程序出现的各种不正常情况都叫做异常。
  • 在Java程序的运行过程中,若Java虚拟机检测出一个无法执行的操作,就会产生Runtime Error
  • 对一个实际为null的对象调用方法:NullPointerException
  • 使用一个越界的下标值来访问数组:ArraylndexOutOfBoundsException
  • 程序需要整数而输入一个double值:InputMismatchException
  • 抛出的异常是一个对象,该对象表示影响程序正常运行的错误或正确情况。
  • Java在调用某个方法时,会抛出异常。
  • 异常:从异常类创建对象。
  • 异常处理:处理异常类的对象。
  • “抛出异常”就是将异常从一个地方传递到另一个地方。
  • 一个try结构可以跟随一个到多个catch,用于捕获不同类型的异常。
  • catch后面的小括号中指定了该catch语句处理的异常类的类型。大括号中包括处理该类型异常的相应代码。
  • 若try结构中某一行代码产生了异常,则该异常被catch块所捕获,catch块中的代码将被运行以处理异常。
  • catch块中的代码执行完之后,不会返回到try块中,而是执行完所有catch块之后的语句。
  • 在抛出异常的情况下,try中的部分语句是被跳过的,不会被java虚拟机运行。因此很少在try中进行变量的定义和初始化。,而且作用域仅限于try块。
  • 开发人员还可以使用throw来手动抛出指定类型的异常。
  • 异常处理机制最更本的优势就是将检测错误与处理错误分离开,检测错误由被调用的方法完成,而处理错误的方法则由方法的调用者来完成。
  • 子类异常写在前,父类异常写在后。

异常的分类

  • 所有异常类的根类是Throwable,该类在java.lang中。
  • 开发者可以通过继承Exception类或Exception的某个子类来创建自己的异常类。
  • java中所有异常类分为两大类:错误和异常。
异常类的第一类是错误
  • 错误由java虚拟机抛出,对应类是error类
  • error类描述的是内部系统错误
  • 常见Error如OutOfMemoryError,表示Java内存溢出StackOverflowError(堆栈溢出错误)该错误一般由于死循环或方法无限递归调用所产生的。
异常类的第二类是异常
  • 异常用Exception类表示,它描述由程序和外部环境所引起的错误,可以被捕获处理。
  • 常见的异常包括前面说的空指针异常NullPointerException,数组下标越界异常:ArraylndexOutOfBoundsException及ClassNotFoundException表示试图使用一个不存在的类。
  • 在读取文件时产生的异常类主要是IOException类。而在SQLException则是访问关系数据库类产生的异常类。
RuntimeException(免检异常)
  • Exception类有一个重要的子类,是RuntimeException类,一般由java虚拟机抛出。
  • ArithmeticException该异常表示数学运算中处以0的情况。
  • lllegalArgumentException该异常表示传递给方法的参数非法或不适合。
  • NullPointerException和ArraylndexOutOfBoundsException 都属于RuntimeException。
checked exception
  • checked exception含义为:可能产生这些类型异常的代码必须采用try-catch结构进行异常处理,或在方法头部中使用throws关键字进行声明。而 unchecked exception非检查异常都不需要。
  • unchecked exception,非检查异常。
  • 所有Error、RuntimeException及其子类都属于unchecked exception.
  • 其他异常都属于checked exception,必检异常。
  • java不强制编写代码捕获或声明unchecked exception。因此在使用数组时可能会产生的数组下标越界或超大数组分配失败导致的内存溢出错误,编程时不需要额外进行处理。
异常处理编程
  • Java的异常处理模型基于以下操作:声明(declar)、抛出(throw)、捕获(catch)
  • 每个方法都必须声明它可能抛出的必检异常的类型,这称为声明异常。
  • Java不要求在方法中显式声明Error和RuntimeException(免检异常),但是,方法要抛出的其他异常都必须在方法头中显式声明。这样方法的调用者会被告知有异常。
  • 为声明一个异常,需要在方法头中使用关键字throws,如
public void myMethod() throws IOException{
//方法体
}

若方法可能抛出多个异常,可在throws后添加一个用逗号分隔的异常列表:

public void myMethod()
        throws Exception1,Exception2,....,ExceptionN
  • 声明异常也是方法签名的一部分,如果父类的方法没有声明某种类型异常,那么在子类中重写该方法时也不能增加声明这种类型的异常。也就是说,==子类方法声明异常的范围不能超过父类方法声明的异常范围。==例如线程类Thread的public void run()方法并未声明任何类型的异常,因此在继承重写该方法时,子类的该方法也不能包含声明异常内容。
抛出异常
  • 检测到错误的程序可以创建一个合适的异常类型并抛出它(throw),例如某个程序发现方法中的参数必须是非负的,而传递给方法的参数是一个负参数,这个程序就可以创建IIIegalArgumentException的实例并抛出它
IllegalArgumentException ex=new IllegalArgumentException("参数错误")//创建一个IllegalArgumentException的对象
throw ex;//抛出异常

或者使用下列语句

throw new IllegalArgumentException("参数错误")
IllegalArgumentException
  • IllegalArgumentException是Java API中的一个异常类
  • 一般Java API中的异常类,都有一个无参构造方法和一个带String类型的构造方法,该String类型的参数称为异常消息,可以调用getMessage()方法来获取该消息。
throws与throw
  • throws用于声明异常,其位置在方法头部的最后,方法体开始的 { 之前
  • throw 则用来抛出异常,其位置在方法体中
  • 若在某方法中使用throw抛出了某种unchecked exception,而该语句并未使用try-catch结构进行异常处理,则throw语句所在的方法必须使用throws进行该异常类的声明,否则会编译错误。
  • 采用throw抛出异常后,本方法的调用即结束,程序的流程直接返回本次方法的调用者那里,尽管被调用的方法代码可能并没有全部执行,也没有执行return语句。这与try块中产生异常之后,直接运行相应的catch块,流程的转移方面二者类似。
捕获异常
  • 当抛出一个异常时,可以在try-catch块中捕获和处理它
  • 如果在执行try块中没有出现异常,则跳过所有的catch子句。若try块中某条语句抛出一个异常,Java就会跳过try块中剩余的语句,然后开始查找处理这个异常代码。
  • 处理这个异常的代码称为异常处理器。
  • 可以从当前的方法开始,沿着方法调用链,按照异常的反向传播方向找到这个处理器
  • 从第一个到最后一个逐个检查catch块,判断在catch块中的异常类实例是否是该异常对象的类型。若是,就将该异常对象赋值给所声明的变量,然后执行catch块中的代码。
  • 若没有发现异常处理器,Java会退出当前方法,并把异常对象传递给调用这个方法的方法,继续同样的过程来查找处理器。
  • 若在调用的方法链中找不到处理器,程序就会终止并且在控制台上打印出错信息,寻找处理器的过程称为捕获一个异常。
  • 从一个通用的父类可以派生出各种异常类。若一个catch块中可以捕获一个父类的异常对象,它就能捕获那个父类所有子类的异常对象。例如,若catch后面使用了Exception类型,那么该catch块就可以处理所有类型的Exception类的对象。这种情况下,用Exception类的句柄引用了实际异常类的对象,这种称为上溯造型,这永远是类型安全的。
  • 在catch块中异常被指定的顺序非常重要,若父类的catch块出现在子类的catch块之前,就会编译错误,因为子类的catch块永远也没法执行。
  • 因此,若catch后的异常类分别是Exception和RuntimeException,那么必须把RuntimeException的catch块放在Exception的catch块之前。
  • 对于使用同样的处理代码处理多个异常的情况,可以使用多捕获特征来简化代码。语法是
catch(Exception1|Exception2|...||Exceptionk ex){
//处理上述异常的代码
}

每个异常类型使用竖线与下一个分割,若其中一个异常被捕获,就会执行异常处理的代码,但用竖线隔开的多个异常类之间不能有继承关系,否则会产生编译错误。

从异常中获取信息
  • 异常对象包含了关于异常的有价值的信息。
  • 可利用java.lang.Throwable类中的实例方法获取有关异常的信息:
  • void printStatckTrace()方法,在控制台上打印栈跟踪信息stackTraceElement[ ] getStackTrace方法,提供编程的方式,来访问由PrintStackTrace()打印输出栈跟踪信息
  • String getMessage()方法返回描述该异常对象的信息;
  • String toString()方法返回三个字符串的连接,1.异常类的全名 2. ": "(一个冒号和空白) 3.getMessage()
finally子句
  • 有时候,不论异常是否出现或是否被捕获,都希望执行某些代码
  • Java有finally子句,可以达到这个目的。
  • finally子句的语法如下所示:
try{
//可能产生异常的代码
}catch(Exception e){
//异常处理代码
}finally{
//finally代码
}
  • 在任何情况下,finally块中的代码都会执行,不论try块中是否出现异常或是否被捕获。
    例如下面三种情况:
  • 若try块中无异常,执行finally子句,然后执行try语句的下一条语句
  • 若try块中有一条语句引起异常,并被catch块捕获,然后跳过try块的其它语句,执行catch块和finally子句。执行try语句之后的下一条语句。
  • 若try块中有一条语句引起异常,但是没有被任何catch块捕获,就会跳过try块中的其他语句,执行finally子句,并将异常传递给这个方法的调用者。
    == 即使在到达finally块之前有一个return语句,finally块还是会执行==
自定义异常类
  • 若遇到一个不能用预定义的异常类恰当描述的问题,就可以通过派生Exception类或其子类如IOException类来创建自己的异常类。
  • NullPointerException从RuntimeException类来继承,通过throw来抛出异常时一般新建一个指定消息值的异常类对象。
  • 自定义异常类的名称为:OutOfEletricityException表示意外情况。该类包含了一个静态的长整型常量,以及两个构造方法。异常类属于
  • OutOfEletricityException属于checked exception因此必须采用try-catch结构进行异常处理,或在方法头部中使用throws关键字进行声明。
何时使用异常
  • 当错误需要被方法的调用者处理的时候,方法应该抛出一个异常。
  • 不要把异常处理用作简单的逻辑测试。
  • try块包含正常情况下的执行代码,Catch块包含异常情况下的执行代码。
  • 异常处理需要初始化新的异常对象,需要从调用栈返回,而且还需要沿着方法调用链来传播异常以便找到它的异常处理器,因此,异常处理需要更多的时间和资源。
    ==异常出现在方法中。==若想让该方法的调用者处理异常,应该创建一个异常对象并将其抛出。若能在发生异常的方法中处理异常,就不需要抛出或使用异常。
    == 一个项目中多个类都会发生的共同异常应该考虑作为一种异常类。==对发生在个别方法中的简单错误最好进行局部处理,无须抛出。
  • 当必须处理不可预料的错误状况时,应该使用try-catch,而不用他处理简单的可预料的情况。
  • NullPointerException(空指针异常)是java中出现次数很高的异常,在对一个没有完成构建的对象(例如null值)调用方法或访问成员变量,就会抛出此类型的异常,该异常属于 unchecked exception,因此不是必须使用try-catch结构进行处理,但也可以使用,不过在编程中更倾向与使用简单的if来进行判断。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值