会出现异常的情况
数组元素下标越界
操作数超出预定范围,例如,除数为0
网络连接中断
想打开的文件不存在
在载入或链接java程序时出错
超出了某些资源限制,例如使用了太多的内存
编程时经常遇到的三类错误
编译错误(Compilation error)
逻辑错误(logic error)
运行时错误(runtime error)在程序运行过程中如果发生了一个不可能执行的操作,就会出现运行时错误
补充说明
编译系统检查出来的语法错误,导致程序运行结果不正确的逻辑错误,都不属于异常的范围
异常是一个可以正确运行的程序在运行中可能发生的错误
特点
偶然性:程序运行中,异常不总是会发生
可预见性:异常的存在和出现是可以预见的
严重性:一旦异常发生,程序可能终止,或者运行的结果不可预知
异常的概念
程序设计的要求之一就是程序的健壮性,希望程序在运行时能够不出或者少出问题。但是,在程序的实际运行时,总会有一些因素会导致程序不能正常运行。例如文件没找到,网络错误,非法的参数,数组越界,被零除等
异常处理就是要提出或者研究一种机制,能够较好地处理程序不能正常运行的问题
异常实际上就是程序中错误导致中断了正常的指令流的一种事件
常规方法处理错误的问题
开发人员的大部分精力花在出错处理
思维的局限性决定:只把能够想到的错误考虑到,对以外的情况无法处理
程序可读性差
出错返回信息量太少
优点
把错误代码从常规代码中分离出来
按错误类型和错误差别分组
系统提供了对于一些无法预测的错误的捕获和处理
克服了传统方法的错误信息有限的问题
Java异常处理
运行时错误会引起异常(exception),没有异常处理代码的程序可能非正常结束,引起严重问题
Java给程序员提供了处理运行时错误的功能,有了这种称为异常处理的功能,就能开发用于重要计算的稳定程序
异常的重要性在于程序不但能发现异常,还能处理异常,使程序正常退出
分类
throwable是所有异常类的父类,它是object的直接子类,是类库java.lang包的一个类
exception类继承自throwable类,所有的throwable类的子孙类所产生的对象都是例外
error:由java虚拟机生成并抛出java程序不做处理
runtime exception:由系统检测,用户的Java程序可不做处理,系统将它们交给缺省的异常处理程序
非runtime exception:java编译器要求java程序必须捕获或声明所有的非运行时异常
throw:用户自己产生异常
Java定义的标准异常类
非受检异常:这些异常只能在程序执行时被检测到,不能在编译时被检测到
非受检异常主要包括runtimeException及其子类
程序对这类异常可不做处理,交由系统处理
受检异常:这些异常在编译时就能被java编译器所检测到异常
除了runtimeException及其子类以外的其它exception的子类都是受检异常,这些异常类是编译时可检测的异常
必须采用声明异常或者try,catch方式处理异常
Java异常处理机制
Java提供的是异常处理的抓抛模型
Java程序的执行过程如出现异常,会自动生成一个异常类对象,该异常对象将被提交给java运行时系统,这个过程称为抛出异常
如果一个方法内抛出异常,该异常会被抛到调用方法中,如果异常没有在调用方法中处理,它继续被抛给这个调用方法的调用者。这个过程将一直继续下去,直到异常被处理,这一过程称为捕获异常
如果一个异常回到main()方法,并且main()也不处理,则程序运行终止
程序员通常只能处理exception,而对error无能为力
异常处理的两种方式:try...catch...finally语句,throws语句
try与catch语句的语法格式:
try{ //接受监视的程序块,在此区域内发生//的异常,由catch中指定的程序处理;}
catch(ExceptionType1 e){ //抛出ExceptionType1异常时要执行的代码 }
catch(ExceptionType2 e){ //抛出ExceptionType2异常时要执行的代码 }
[ finally { // // 无条件执行的语句 } ]
捕获异常的有关信息
与其他对象一样,可以访问一个异常对象的成员变量或调用它的方法
getMessage()方法,用来得到有关异常事件的信息
printStackTrace()用来跟踪异常事件发生时执行堆栈的内容
在Java语言中使用语句try...catch...finally进行异常处理,程序流程从引起异常的代码转移到最近的try语句的catch子句
注意
同一段程序可能产生不止一种异常,你可以放置多个catch子句来检查每一种异常类型,第一个与异常匹配的catch将会被执行
如果一个异常类和其子类都出现在catch子句中,应把子类放在前面,否则将永远不会到达子类
finally语句
实际应用中,确保一段代码不管发生什么异常都能被执行是必要的,关键字finally就是用来标识这样一段代码的
即使没有catch子句,finally语句块也会在执行了try语句块后立即执行
throws语句 - 声明异常
声明异常:一个方法不处理它产生的异常,而是沿着调用层次向上传递,由调用它的方法来处理这些异常,叫声明异常
throws语句用来表明一个方法可能抛出的各种异常,并说明该方法会抛出但不捕获异常
如果最终方法也没有处理异常,异常将交给系统处理
建议
对于程序中需要处理的异常,一般编写try - catch - finally语句捕获并处理
而对于程序中不需要处理的异常,可以使用throws语句在方法抛出异常交由系统处理
重写方法声明抛出异常的原则
重写方法不能抛出比被重写方法范围更大的异常类型
创建自己的异常
不是由Java 系统监测到的异常(下标越界,被0除等),而是由用户自己定义的异常
用户定义的异常同样要用try ... catch捕获,但必须由用户自己抛出throw new MyException
异常是一个类,用户定义的异常必须继承自Throwable或者Exception类,建议用Exception类
Throw语句 - 抛出异常
在前面讲述的例子中,异常对象是由Java在运行时由系统抛出的
程序中显示生成异常:抛出异常也可以通过代码来实现,throw语句可以明确的抛出一个异常
throw抛出异常主要用于自定义异常
throw语句格式:< throw ><异常对象>
程序会在throw语句处立即终止,转向try ... catch寻找异常处理方法