Java中的异常处理机制
异常机制已成为判断1门编程语言是不是成熟的标准,异常机制可使程序中异常处理代码和正常业务代码分离,保证程序代码更加优雅,并提高程序硬朗性。 Java异常机制主要依赖于try、catch、finally、throw、throws5个关键字。 1.try:它里面放置可能引发异常的代码 2.catch:后面对应异常类型和1个代码块,用于表明该catch块用于处理这类类型的代码块,可以有多个catch块。 3.finally:主要用于回收在try块里打开的物力资源(如数据库连接、网络连接和磁盘文件),异常机制总是保证finally块总是被履行。只有finally块,履行完成以后,才会回来履行try或catch块中的return或throw语句,如果finally中使用了return或 throw等终止方法的语句,则就不会跳回履行,直接停止。 4.throw:用于抛出1个实际的异常,可以单独作为语句使用,抛出1个具体的异常对象。 5.throws:用在方法签名中,用于声明该方法可能抛出的异常。
Java的异常分为两种,checked异常(编译时异常)和Runtime异常(运行时异常) 1. java认为checked异常都是可以再编译阶段被处理的异常,所以它强迫程序处理所有的checked异常,而Runtime异常不必处理,java程序必须显式处理checked异常,如果程序没有处理,则在编译时会产生毛病,没法通过编译。 2. checked异常体现了java设计哲学:没有完善处理的代码根本不会被履行,体现了java的严谨性, 对构造大型、硬朗、可保护的利用系统而言,毛病处理是全部利用需要斟酌的重要方面。Java异常处理机制,在程序运行出现意外时,系统会生成1个Exception对象,来通知程序,从而实现将“业务功能实现代码”和“毛病处理代码”分离,提供更好的可读性。 如果履行try块里的业务逻辑代码时出现异常,系统会自动生成1个异常对象,该异常对象被提交给运行环境,这个进程被称为抛出(throw)异常。Java环境收到异常对象时,会寻觅适合的catch块,如果找不到,java运行环境就会终止,java程序将退出。 不同的catch块,视为了针对不同的异常类,提供不同的处理方法。 对毛病处理机制,主要有以下的两个缺点: 1.没法穷举所有异常情况:由于人类的知识是有限的,异常情况总比可以斟酌到的情况多,总有漏网之鱼 2.毛病处理代码和业务实现代码混杂严重影响程序的可读性,会增加程序保护的难度。 1.使用try...catch捕获异常 java提出了1种假定,如果程序可以顺利完成,那末1切正常,把系统的业务实现代码放在try块中定义,所有的异常处理逻辑放在catch块中进行处理。 即:try{ //业务实现代码 ... } catch(Exception e){ 输入不合法 上面的格式中try块和catch块后的{...}都是不可以省略的! 履行步骤: 1.如果履行try块中的业务逻辑代码时出现异常,系统自动生成1个异常对象,该异常对象被提交给java运行环境,这个进程称为抛出(throw)异常。 2.当java运行环境收到异常对象时,会寻觅能处理该异常对象的catch块,如果找到适合的cathc块并把该异常对象交给catch块处理,那这个进程称为捕获(catch)异常;如果java运行时环境找不到捕获异常的catch块,则运行时环境终止,jav程序也将退出。 注意1:不管程序代码块是不是处于try块中,乃至包括catch块中代码,只要履行该代码时出现了异常,系统都会自动生成1个异常对象,如果程序没有为这段代码定义任何catch块,java运行环境肯定找不到处理该异常的catch块,程序肯定在此退出。 注意2:try块后可以有多个catch块,try块后使用多个catch块是为了针对不同异常类提供的不同的异常处理方式。当系统产生不同意外情况时,系统会生成不同的异常对象,java运行时就会根据该异常对象所属的异常类来决定使用哪一个catch块来处理该异常。 注意3:通常情况下,如果try块被履行1次,则try块后只有1个catch块会被履行,绝不可能有多个catch块被履行,除非在循环中使用类continue开始下1次循环,下1次循环又重新运行了try块,这才可能致使多个catch块被履行。 注意4:进行异常捕获时,1定要记住先捕获小的异常,再捕获大的异常。 Java的异常类,和他们的继承关系:
java把所有非正常情况分成两种:异常(Exception)和毛病(Error),都是继承自Throwable父类。 Error毛病:1般是指虚拟机相干的问题,如系统崩溃,虚拟机出毛病等,这类毛病没法恢复或不可能捕获,将致使利用程序中断,通常不处理。
Throwable(): 1.Error(毛病):1般是指java虚拟机相干的问题,如系统崩溃、虚拟机出毛病、动态链接失败等,这类毛病没法恢复或不可能捕获,将致使利用程序中断,通常利用程序没法处理这些毛病,因此利用程序不应当捕获Error对象,也不必在其throws子句中声明该方法抛出任何Error或其子类。
2.Exception: (1). SQLException:该异常提供关于数据库访问毛病或其他毛病的信息。
(2). (3).IOException:此类为异常的通用类,它是由失败的或中断的 I/O 操作生成的。 异常对象包括的经常使用方法: 1. getMessage();返回该异常的详细描写字符 2. printStackTrace():将该异常的跟踪栈信息输出到标准毛病输出。 3. printStackTrace(PrintStream s):将该异常的跟踪栈信息输出到指定的输出流 4. getStackTrace():返回该异常的跟踪栈信息。 1 public class TestException 2 { 3 4 static void main(String[] args) 5 { 6 7 try{ 8 FileInputStream fis=new FileInputStream("a.txt"); 9 } 10 catch(IOException ioe) 11 { 12 System.out.println(ioe.getMessage()); 13 ioe.printStackTrace(); 14 } 15 16 } 17 18 } 使用finally回收资源 有时候,程序在try块里面打开了1些物力资源(比如数据库连接,网络连接好磁盘文件等),这些物理资源都必须显式回收。 由于:java的垃圾回收机制不会回收任何的物理资源,垃圾回收机制只回收堆内存中对象所占用的内存。 问题1:那末在哪边回收这些物理资源呢? 答:在finally块中,由于如果try块的某条语句引发1场,该语句后的其他语句通常不会被履行,那将致使位于该语句后的资源回收语句得不到履行;如果在catch块里进行资源回收,但catch块完全有可能得不到履行,这也将致使不能及时回收这些物理资源。所以我们不管try块中的代码是不是出现异常,也不管哪一个catch块会被履行,finally块总会被履行。 那末:java异常处理的完全语法结构以下:
try
以上的异常处理语法结构中 import java.io.FileInputStream;
2 import java.io.IOException;
/**
8 * @param args
9 */
12 // TODO Auto-generated method stub
13 FileInputStream fis = null;
14 try
15 {
16 fis = 17 } catch (IOException ioe)
18 {
19 System.out.println(ioe.getMessage());
20 return语句强迫方法返回
21 return;
22 使用exit来退出虚拟机
23 System.exit(1);
24 } finally
25 {
26 关闭磁盘文件,回收资源
27 if (fis != null)
28 {
29 30 {
31 fis.close();
32 } 33 {
34 ioe.printStackTrace();
35 }
36 }
37 System.out.println("程序已履行了finally里德资源回收");
38 }
39 }
40
41 }
运行程序结果: 如果将catch块中的最后两句注释放入程序,那末结果为:a.txt (系统找不到指定的文件。) 以上两种情况显示:除非在try块或catch块中调用了退出虚拟机的方法(即System.exit(1);),否则不管在try块、catch块中履行怎样的代码,出现怎样的情况,异常处理的finally块总是会被履行的。不过,1般情况下,不要再finally块中使用renturn或throw等致使方法终止的语句,由于1旦使用,将会致使try块、catch块中的return、throw语句失效。
class TestException1
4 boolean test()
5 {
6 7 {
8 return true;
9 } 10 {
11 false;
12 }
13 }
14
15 16 {
17 boolean a = test();
18 System.out.println(a);
19 }
20
21 }
运行结果:false 以上的小程序说明:在finally块中定义了1个renturn false语句,这将致使try块中的return true 失去作用! 总结1下这个小问题: 当程序履行try块,catch块时遇到return语句或throw语句,这两个语句都会致使该方法立即结束,所以系统其实不会立即履行这两个语句,而是去寻觅该异常处理流程中的finally块,如果没有finally块,程序立即履行return语句或throw语句,方法终止。如果有finally块,系统立即开始履行finally块,只有当finally块履行完成后,系统才会再次跳回来履行try块、catch块里的return或throw语句,如果finally块里也使用了return或throw等致使方法终止的语句,则finally块已终止了方法,不用再跳回去履行try块、catch块里的任何代码了。 综上:尽可能避免在finally块里使用return或throw等致使方法终止的语句,否则可能出现1些很奇怪的情况! 异常处理的嵌套 例如catch块中再次包括了1个完全的异常处理流程,这类在try块,catch块或finally块中包括完全的异常处理流程的情形称为异常处理的嵌套。异常处理流程的代码可以放在任何可履行代码的地方,因此完全的异常处理流程既可放在try块,也可放在catch块,也可放在finally块里。 嵌套的深度没有很明确的限制,通常没有必要写层次太深的嵌套异常处理,会致使程序可读性下降。 Checked异常和Runtime异常体系 java异常被分为两大类:Checked异常和Runtime异常(运行时异常)。 所有RuntimeException类及其子类的实例被称为Runtime异常,不是RuntimeException类及其子类的异常实例则被称为Checked异常。 只有java语言提供了Checked异常,其他语言都没有提供,java认为Checked异常都是可以被处理(修复)的异常,所以java程序不必显式的处理Checked异常。如果程序没有处理Checked异常,该程序在编译时就会产生毛病,没法通过编译。 Checked异常的处理方式: ①:当方法明确知道如何处理异常,程序应当使用try...catch块来捕获该异常,然后在对应的catch块中修补该异常。 ②:当方法不知道如何处理异常,应当在定义该方法时声明抛出该异常。 Runtime异常不必显式声明抛出,如果程序需要捕捉Runtime异常,也能够使用try...catch块来捕获Runtime异常。 问题是:大部份的方法总是不能明确知道如何处理异常,这就只能声明抛出异常了。 使用throws抛出异常 使用throws抛出异常的思路是:当前方法不知道如何处理这类类型的异常,该异常应当由上1级调用者处理,如果main方法也不知道应当如何处理这类类型的异常,也能够使用使用throws声明抛出异常,该异常将交给JVM来处理。 JVM对异常的处理方法:打印异常跟踪栈的信息,并终止程序运行,所以有很多程序遇到异常后自动结束。 使用throws抛出异常的格式: throws声明的抛出的语法格式紧跟在方法以后,可以声明多个异常类,多个异常类之间以逗号隔开。1旦使用了throws语句声明抛出异常,就不用再使用try...catch来捕获异常了。 如:throws ExceptionClass1,ExceptionClass2... 注意点1:如果某段代码调用了1个带throws声明的方法,该方法声明抛出了Checked异常,这表明该方法希望它的调用者来处理该异常。那末这段代码要末放在try块中显示捕获该异常,要末这段代码处于另外一个带throws声明抛出的方法中。 举例以下: 方法1:
2
3 5
6 class TestException2
7 {
8
9 test() 方法抛出了异常,那末test()方法的调用者要末放在try块中显示捕获该异常,要末这段代码处于另外一个带throws声明抛出的方法中。
10
11 以下为后者的处理方法
12
13 void test() throws IOException
14 {
15 FileInputStream fis = 16 }
18 void main(String[] args) throws Exception
19 {
20 test();
21 }
22
23 }
方法2:
(编辑:李大同)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |