赞
踩
7000字的文章,实属不易,如果看着合适请动动小手点点关注,点点点赞,点点收藏吧,谢谢!
不喜勿喷,谢谢!
使用工具 IntelliJ IDEA Community Edition 2023.1.4
使用语言 Java8/JDK1.8
目录
2.2.2 2.使用try-catch-finally语句处理异常
在生活中,异常情况随身都有可能发生。下面将从生活中的异常过渡到程序,帮助大家建立对异常的初步认识。
在日常生活中,几乎随时随处可能出现意外情况。以学校生活为例,在上学的路上发生交通事故或拥堵、教员生病、教室投影不能正常使用、机房网络感染病毒等,这些都是意外情况。虽然这些意外情况是偶然事件,但是一旦发生就会带来不小的麻烦,影响正常的学习生活。同理,在程序中也会发生类似的情况,下面看看程序中的异常。
在程序开发过程中, 程序员虽然会尽量避免错误的发生,但是总会遇到一些不可预期的问题,如除法运算时除数为0、数组下标越界、数据类型不一致、内存不足、栈溢出等,这些就是异常。
在计算机的发展中有两大计算"杀手",一个是断点,另外一个是除数为0.因为除数在为0在数学的解是无穷大,对于计算机来说,如果是无穷大,则意味着内存将全部占满,所以,在程序开发中,务必避免除数为0的情况。
在程序设计时,必须考虑到可能发生的异常事件并进行相应的处理,这样才能保证程序正常运行。
Java的异常处理机制也秉承着面向对象的基本思想,在Java中,所有的异常都定义为类。除了内置的异常类,Java也可以自定义异常类。此外,Java的异常处理机制也允许自行抛出异常。
Java针对异常的处理提供了try、catch、finally、throws。throw五个核心关键字,其中前三个关键字就可以组成常用的异常处理结构,语法如下:
try{
//有可能出现异常的语句
}
[catch(异常类型 异常对象){
//异常处理语句
}]
[finally{
//一定会允许到的语句
}]
其中,try语句用于监听,将可能抛出异常的代码放在try语句块内,当try语句块内发生异常时,异常就会被抛出;catch语句用于捕获异常,catch语句用来捕获try语句块中抛出的异常;finally语句块总会被执行,主要用于回收try语句块内打开的资源,如数据库连接,网络连接和磁盘文件。
以上个事中的catch语句、finally语句都可选。实际上,这并不是表示catch语句、finally语句可以同时消失。异常格式的常见组合有try-catch、try-catch-finally、try-finally三种。
以上程序使用了异常处理语句,当程序出现异常时,异常会被try语句监听到,然后被JVM(Java虚拟机)抛出,被catch语句捕获进行处理,执行catch语句内的异常处理代码,不再需要程序员自行编写if语句进行判断,简化了代码。
使用Java异常处理机制的目的是帮助程序员发现异常并解决异常。以上代码中采用输出错误提示的发生处理异常,不能明确地描述异常类型,不能精确定位问题所在。更好的方法是使用异常类中提供的printStackTrace()方法进行异常信息但完整输出。
捕获异常中的异常对象.printStackTrace();即可进行异常信息的完整输出。
从上述代码可以看出,Java异常处理机制可以自动捕获不同类型的异常。如果try语句块在执行过程中遇到异常,则异常处之后的代码将不再被执行,系统会将异常信息封装成相应类型的异常对象,包含异常的类型、异常出现时程序的运行状态及对该异常的详细描述。如果这个异常对象与catch语句中声明的异常类型相匹配,则会被自动捕获,Java异常处理机制把该异常对象赋给catch关键字后的异常参数,执行catch语句块中的语句。Exception类型的常用方法如下:
void printStackTrace()
输出异常堆栈信息。堆栈信息中包含程序运行到当前类的执行流程,它将输出从方法调用处到异常抛出处的方法调用序列。
String getMessage()
返回异常的详细信息。该信息描述异常产生的原因,是printStackTrace()方法输出信息的一部分。
因为使用printStackTrace()方法输出的异常信息是最完整的,所以后续会使用该方法进行异常信息输出。在其输出结果中,可以自下向上观察程序的运行轨迹,最终定位到异常发生的位置。
如果程序出现异常,程序将自动跳转到catch语句块处理异常,后续输出语句将不再被执行。如果需要继续执行后面的语句,则需要添加finally语句。
finally语句块中的代码,无论是否出现异常,最终都会执行finally语句块的代码。
即使在try语句块或catch语句块中添加了return语句,finally语句块也会被正常执行。
那么,是否有finally语句块不被执行的情况呢?
答:在异常处理代码中执行System.exit(1),将退出JVM。
在之前的案例中,程序出现的全部异常由统一的处理方式。但在实际开发中,有时会希望针对不同的异常类型采取不同的处理方式,这样就需要使用多重catch语句进行异常处理。语法如下:
try{
//有可能出现异常的语句
}
[catch(异常类型1 异常对象){
//异常处理语句1
}]
[catch(异常类型2 异常对象){
//异常处理语句2
}]
[finally{
//一定会允许到的语句
}]
算数异常(ArthmeticException)
输入类型不匹配异常(InputMismatchException)
前面已经介绍了异常处理及其对程序正常执行的重要性。为了能更好地理解异常的继承结构,必须理解异常的继承结构及处理流程。
所有的异常类型都继承Java.lang.Throwable类,它有两个重要的子类,分别是Error类和Exception类。
Java.lang.Error类包含仅靠程序本身无法恢复的严重错误,是Java运行环境的内部错误或硬件问题,如内存资源不足、JVM错误等。应用程序不应该抛出这种类型的对象(一般由JVM抛出)。假如出现这种错误,除尽力使程序安全退出外,其他方法是无能为力的。因此在程序设计时,应该更关注Exception类。
Java.lang.Exception类是程序本身可以处理的异常,可分为运行时(RunTimeException)异常与检查(Checked)异常。
可以在程序中避免的异常。这类异常在编译代码时不会被编译器检测出来,可以正常编译运行,但当程序进行时发生异常,会输出异常堆栈信息并中止程序执行,程序员可以根据需要使用try-catch语句捕获这类异常,如空指针异常、类型转换异常、数组越界异常等,这些异常包括Java.long.RuntimeException类及其子类,通过这些具体的异常类型,能够判断程序的问题所在。Java程序中常见的运行时异常如下:
常见异常
ArithmeticException
当出现算数错误时,抛出此异常。例如,在一个整数"除以0"时,抛出此异常
ArrayIndexOutOfBoundsException
当非法索引访问数组时,抛出此异常。例如,索引为负或大于等于数组长度
ClassCastException
当试图将对象强制转换为非本对象类型的子类时,抛出此异常
IllegalArgumentException
当向方法传递了一个不合法或不正确的参数时,抛出此异常
InputMismatchException
当欲得到的数据类型和实际输入的类型不匹配时,抛出此异常
NullPointerException
当应用程序试图在需要对象的地方使用null时,抛出此异常
NumberFormatException
当试图将字符串转换成一种数值类型,但该字符串不能转换为适当格式时,抛出此异常。例如,把"ABC"转换为数字
除运行时的异常,是由用户错误或问题引起的异常,这是程序员无法遇见的。在编译时,编译器会提示这类异常需要捕获。如果不进行捕获,则会出现编译错误。常见的编译异常由FileNotFoundException(Java字节输入流/Java字节输出流)异常、SQLException(Java连接数据库)异常等。
FileNotFoundException异常和IOException异常为Checked异常,必须进行异常处理才能通过编译。
在Java中进行异常类子类命名时都会使用XXXError或XXXException的形式,这样也是为了从名称上帮助开发人员进行区分。
整个过程类似于方法传参,所生成的异常对象根据catch语句后面的参数进行匹配,依据Java面向对象中向上转型的原理,所有异常对象都可以向其父类进行类型转换,所以所有的异常对象都可以使用Exception对象来接收。当无需对异常进行细分处理时,就可以简单地实现异常处理;否则,就需要使用多重catch语句对每类异常分别处理。
如果根据程序的设计,不适合立即去处理异常,而应声明可能发生异常,交由上一级(声明的异常)处理,此时,就需要使用throws关键字。
throws关键字是方法可能抛出异常的声明,用在所声明的方法时,表示该方法可能会抛出此类异常。语法如下:
public void 方法名() throws 异常类型[,异常类型]{
//方法体
}
throws关键字可以在一个方法定义处声明一类或多类异常,多类异常间使用逗号分隔。
声明异常后调用者有以下两种处理方式。
public static void main(String[] args) throws Exception{
//声明异常由JVM处理
}
throws 关键字用于在方法声明中指定该方法可能抛出的异常。当方法内部抛出指定类型的异常时,该异常会被传递给调用该方法的代码,并在该代码中处理异常。
从实际开发的角度来讲,main()方法不建议声明异常,因为如果程序出现了错误,会导致程序中断执行。
用这个的好处是如果有多个方法都可以用一个try语句来进行异常处理然后抛出异常(在后面的Java多线程中有用)。
使用try-catch-finally语句进行异常处理,在这个异常处理结构中,由JVM进行判断并抛出异常信息,也就是程序遇到异常时会自动处理。但是有时可能会出现如下状况:
在以上情况中,就需要使用throw关键字自行手动抛出异常,由调用者处理抛出异常的时机和异常的处理逻辑。由于使用throw关键字抛出的异常是异常类的对象,所以可以使用new关键字创建异常类的对象,通过throw关键字抛出,语法如下:
throw new 异常名([参数列表]);
使用throw关键字抛出的只能是Throwable类或其子类的对象,下面的语句是错误的
throw new String("exception");
因为String类不是Throwable类的子类
上面的代码并不难理解,因为当异常发生时一定会由系统产生一个异常类的实例化对象,只是此时异常类的实例化对象是通过手动创建并使用throw关键字抛出的而已。
使用自定义异常时最后需要在对应的catch语句块中点打印异常信息方法(printStackTrace);
或者用throws关键字吧可能发生的异常声明为异常的父类Exception,这样就可以使用Exception直接调用打印方法,打印的是对应异常的方法
当Java异常体系中提供的异常类型不能满足程序的需要时,可以自定义异常类,使用自定义异常一般有三个步骤:
使用throw关键字可以抛出自定义异常,那么自定义异常有哪些应用场景呢?
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。