学习Java的同学注意了!!!
学习进程中遇到甚么问题或想获得学习资源的话,欢迎加入Java学习交换群,群号码:183993990 我们1起学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():Throwable
类是 Java 语言中所有毛病或异常的超类。只有当对象是此类(或其子类之1)的实例时,才能通过 Java 虚拟机或 Java throw
语句抛出。类似地,只有此类或其子类之1才可以是 catch
子句中的参数类型。
1.Error(毛病):1般是指java虚拟机相干的问题,如系统崩溃、虚拟机出毛病、动态链接失败等,这类毛病没法恢复或不可能捕获,将致使利用程序中断,通常利用程序没法处理这些毛病,因此利用程序不应当捕获Error对象,也不必在其throws子句中声明该方法抛出任何Error或其子类。
2.Exception:Exception
类及其子类是 Throwable
的1种情势,它指出了公道的利用程序想要捕获的条件
(1). SQLException:该异常提供关于数据库访问毛病或其他毛病的信息。
(2). RuntimeException
是那些可能在 Java 虚拟机正常运行期间抛出的异常的超类
(3).IOException:此类为异常的通用类,它是由失败的或中断的 I/O 操作生成的。
异常对象包括的经常使用方法:
1. getMessage();返回该异常的详细描写字符
2. printStackTrace():将该异常的跟踪栈信息输出到标准毛病输出。
3. printStackTrace(PrintStream s):将该异常的跟踪栈信息输出到指定的输出流
4. getStackTrace():返回该异常的跟踪栈信息。
1 public class TestException 2 { 3 4 public 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
{
//业务实现逻辑
...
}
catch(SubException e)
{
//异常处理快1
...
}
catch(SubException2 e)
{
//异常处理快2
...
}
...
finally
{
//资源回收块
...
}
以上的异常处理语法结构中
注意点1:只有try块石必须的,也就是说如果没有try块,则不可能有后面的catch块和finally块;
注意点2:catch块和finally块都是可选的,但catch块和finally块最少出现其中之1,也能够同时出现;
注意点3:可以有多个catch块,捕获父类异常的catch块必须位于捕获子类异常的后面;
注意点4:不能只有try块,既没有catch块,也没有finally块;
注意点5:多个catch块必须位于try块以后,finally块必须位于所有catch块以后。
1 import java.io.FileInputStream; 2 import java.io.IOException; 3 4 public class TestException 5 { 6 7 /** 8 * @param args 9 */ 10 public static void main(String[] args) 11 { 12 // TODO Auto-generated method stub 13 FileInputStream fis = null; 14 try 15 { 16 fis = new FileInputStream("a.txt"); 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 try 30 { 31 fis.close(); 32 } catch (IOException ioe) 33 { 34 ioe.printStackTrace(); 35 } 36 } 37 System.out.println("程序已履行了finally里德资源回收"); 38 } 39 } 40 41 }
运行程序结果:
a.txt (系统找不到指定的文件。)
程序已履行了finally里德资源回收
如果将catch块中的最后两句注释放入程序,那末结果为:a.txt (系统找不到指定的文件。)
以上两种情况显示:除非在try块或catch块中调用了退出虚拟机的方法(即System.exit(1);),否则不管在try块、catch块中履行怎样的代码,出现怎样的情况,异常处理的finally块总是会被履行的。不过,1般情况下,不要再finally块中使用renturn或throw等致使方法终止的语句,由于1旦使用,将会致使try块、catch块中的return、throw语句失效。
1 public class TestException1 2 { 3 4 public static boolean test() 5 { 6 try 7 { 8 return true; 9 } finally 10 { 11 return false; 12 } 13 } 14 15 public static void main(String[] args) 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 //方法1: 2 3 import java.io.FileInputStream; 4 import java.io.IOException; 5 6 public class TestException2 7 { 8 9 // test() 方法抛出了异常,那末test()方法的调用者要末放在try块中显示捕获该异常,要末这段代码处于另外一个带throws声明抛出的方法中。 10 11 // 以下为后者的处理方法 12 13 public static void test() throws IOException 14 { 15 FileInputStream fis = new FileInputStream("a.txt"); 16 } 17 18 public static void main(String[] args) throws Exception 19 { 20 test(); 21 } 22 23 }
1 //方法2: 2 3 import java.io.FileInputStream; 4 import java.io.IOException; 5 6 public class TestException2 7 { 8
下一篇 Android数据存储与IO