加入异常处理操做,会增长程序的容错性,会减小程序由于某些情况的发生忽然退出的状况。java
异常机制可使程序中的异常处理代码和正常业务代码分离,保证程序代码更加优雅,并能够提升程序的健壮性。程序员
五个关键词:try、catch、finally、throw和throws数据库
Java的异常能够分为两种:Checked异常和Runtime异常。网络
Checked异常都是能够在编译阶段被处理的异常,因此它强制程序处理全部的Checked异常。spa
Checked异常要么显式声明抛出;要么显式捕获并处理它。code
而Runtime异常则无需处理。对象
Error为错误,Exception为异常。Exception中RuntimeException为Runtime异常,其余都为Checked异常。接口
Checked异常至少存在两大不便: ①对于程序中的Checked异常,java要求必须显式捕获并处理该异常或者显式声明抛出该异常; ②若是在方法中显式的声明抛出Check异常,将会致使方法签名与异常耦合,若是该方法是重写父类的方法,则该方法抛出的异常还会受到被重写方法的所抛出异常的限制。资源
大部分时候推荐Runtime异常,而不使用Check异常。字符串
runtime异常优势:正常代码和错误处理代码分离;保证程序具备较好健壮性;避免checked的繁琐性。
checked异常优势:能在编译时体型程序员代码可能存在的问题,体型程序员必须注意处理该异常。
if(用户输入不合法) { alert 输入不合法 goto retry } else { 业务实现代码 }
常见的代码中若是单纯使用if else语句实现错误处理机制,主要存在两个缺点:
①没法穷举全部的异常状况②错误处理代码和业务实现代码混杂。
异常处理机制的过程:
当程序运行出现意外状况时,系统会自动生成一个Exception对象来通知程序。 能够采用try...catch捕获异常; 或者使用throws抛出异常到上一层,但目标仍是寻找catch来捕获异常,若是一直没有找到对应的catch块,那么异常就会一直向抛出,直处处于JVM层次时,JVM处理,JVM处理异常的方式是,打印异常的跟踪栈信息,并终止运行(这就是通常程序遇到异常后自动结束的缘由)。
1.try...catch捕获异常
try { 业务实现代码 } catch (Exception e) { alert 输入不合法 goto retry }
若是try块里的业务逻辑代码出现异常,系统自动生成一个异常对象,该异常对象被提交给Java运行环境时,这个过程被称为抛出异常,此时Java运行环境寻找能处理该异常对象的catch块,找到并交给catch块处理成为捕获异常。
每次try之后,catch块至多只能运行一个。如图,Exception放在最后,也是由于若是它在最前面,那么它必将捕获异常,而它的子类也就没有用了;而放到最后,可以为其子类增长了一个捕获未知异常的功能。也即“先处理小异常,再处理大异常”。
异常处理的嵌套:在try块、catch块或finally块中包含完整的异常处理流程的情形被称为异常处理的嵌套。一般没有必要使用两次以上的必要,会下降程序可读性。
Java7新增的多异常捕获:
①捕获多种类型的异常时,多种异常类型之间用竖线(|)隔开。
②捕获多种类型的异常时,异常变量有隐式的final修饰,以此程序不能对异常变量从新赋值。
如图所示:
访问异常信息:全部的异常对象都包含了以下几个经常使用方法:
①getMessage():返回该异常的详细描述字符串
②printStackTrance():将该异常的跟踪栈信息输出到标准错误输出。
③printStackTrance(PrintStream s):将该异常的跟踪栈信息输出到指定输出流。
④getStackTrance():返回该异常的跟踪栈信息
2.finally回收资源
有些时候,程序在try块里打开了一些物力资源(例如数据库链接、网络链接和磁盘文件等),这些物力资源都必须显示回收。
异常处理语法结构,只有try块是必须的;catch和finally至少出现其中之一。
try { //return 在调用return之前会先调用finally块,再调用return; //System.exit(1); 退出虚拟机,再也不执行finally块 } finally { }
注意:一旦在finally块中使用了return和throw语句,将会致使try块、catch块中的return、throw语句失效。
java7加强的自动关闭资源的try语句(隐式的finally块):
它容许在try关键字后紧跟一对圆括号,圆括号里能够声明、初始化一个或多个资源,此处的资源指的是那些必须在程序结束时显式关闭的资源。
为了保证try语句能够正常关闭资源,这些资源实现类必须实现AutoCloseable(抛出了Exception)或Closeable接口(抛出了IOException),实现这两个接口就必须实现close()方法。
java9再次加强了try语句块:
再也不须要圆括号声明,只须要自动关闭的资源有finally修饰或者是有效的final(effectively final)(虽然没有final修饰,可是再也不对该变量从新赋值)。
3.使用throws声明抛出异常
思路:当前方法不知道如何处理这种类型的异常,该异常应该由上一级使用者处理;若是main方法一不知道如何处理这种类型的异常,也可使用throws声明抛出异常,该异常将交给JVM处理。
public void main(String []args) throws IOException { }
使用throws声明抛出异常时有一个限制,就是重写时“两小”中的一条规则: ①子类方法声明抛出的异常类型应该是父类方法声明抛出的异常类型的子类或相同。 ②子类方法声明抛出的异常不容许比父类方法声明抛出的异常多。
4.使用throw抛出异常
当程序出现错误时,系统会自动抛出异常;除此以外,java也容许程序自行抛出异常,自行抛出异常使用throw语句来完成。
throw抛出的不是一个异常类,而是一个异常实例。
public class ThrowTest{ public static void main(String []args) { try { //调用声明抛出Checked异常的方法,要么显式捕捉该异常,要么在main方法中再次声明抛出 throwChecked(-3); } catch(Exception e) { System.out.println(e.getMessage()); } //调用声明抛出Runtime异常的方法既能够显式捕获该异常,也能够不理会该异常 throwRuntime(3); } public static void throwChecked(int a)throws Exception{ if(a>0) { //自行抛出Exception异常,该代码必须处于try块里,或者处于带throws声明的方法里 throw new Exception("a的值大于0,不符合要求"); } } public static void throwRuntime(int a) { if(a>0) { //自行抛出RuntimeException异常,既能够显式捕获该异常, //也能够彻底不理会该异常,把该异常交给方法处理器调用 throw new RuntimeException("a的值大于0,不符合要求"); } } }