Java 异常处理
Java 异常的捕捉和处理
异常是Java的特色,合理的使用异常处理,可以让程序代码更加的完美。
异常是导致程序中断执行的一种指令流,异常一旦出现并且没有进行合理处理的化,那么程序将会中断执行。
无异常的Code:
public class TestDemo { public static void main(String [] args) { System.out.println("\t开始") ; System.out.println(">>> " + (10/2)) ; System.out.println("\t结束") ; } } |
产生异常的Code:
public class TestDemo { public static void main(String [] args) { System.out.println("\t开始") ; System.out.println(">>> " + (10/0)) ; //产生异常 System.out.println("\t结束") ; } }
|
分析code后发现,一旦异常发送,在异常之后的语句将不在执行,默认情况下,输出异常的错误信息,不再输出后面的code;
而异常的处理,则是即使出现了异常,那么也要让程序可以正确的执行完毕。
处理异常:
在Java中提供了三个关键字来处理异常:try、catch、finally
异常处理语法:
try { // 有可能出现异常的语句 } catch (异常类型 对象) { // 异常处理 ; } ····· //可以利用catch处理多种异常 [finally {/* 无论是否出现异常都会执行的统一代码语句*/}]
组合方式: try … catch try … catch … finally try … finally |
应用异常处理格式:
public class TestDemo { public static void main(String [] args) { System.out.println("\t开始") ; try { System.out.println(">>> " + (10/0)) ; } catch (ArithmeticException e) { System.out.println("异常报错") ; } System.out.println("\t结束") ; } }
|
在try中发现了异常,则会找到catch输出异常处理的语句;应用异常处理格式后,即使发现了异常,也会在运行catch后,继续执行,直至直至执行完毕;
出现异常则是为了解决异常,为了便于异常代码的处理,可以使用异常类提供的printStackTrace()方法进行异常信息的完整输出。
public class TestDemo { public static void main(String [] args) { System.out.println("\t开始") ; try { System.out.println(">>> " + (10/0)) ; } catch (ArithmeticException e) { //System.out.println("异常报错") ; e.printStackTrace() ;
} System.out.println("\t结束") ; } }
|
由此可知,可以使用异常类提供的方法,来输出异常的报错信息,便利于程序的修改完善。
异常报错信息包含:异常类型、异常位置、以及具体的行号
public class TestDemo { public static void main(String [] args) { System.out.println("\t开始") ; try { System.out.println(">>> " + (10/0)) ; } catch (ArithmeticException e) { //System.out.println("异常报错") ; e.printStackTrace() ; } finally { System.out.println("不管是否出现异常都执行finally"); } System.out.println("\t结束") ; } } |
在异常捕获的时候,一个try语句中可以包含多个catch语句?因为try中的异常不仅仅只有一种异常类型,如果有异常没有被catch处理,依旧会导致程序中断执行,而多个catch语句可以兼容的处理多个不同的异常;
异常的处理流程:
ArithmeticException |
NumberFormatException |
Java.lang.Object Java.lang.Throwable Java.lang.Exception Java.lang.RuntimeException Java.lang.ArithmeticException |
Java.lang.object Java.lang.Throwable Java.lang.Exception Java.lang.RuntimeException Java.lang.lllegalArgumentException Java.lang. NumberFormatException |
经过异常类的比较发现,所有的异常都来自于Throwable子类:在Throwable子类下有两个已知的子类:Error和Exception ;
Error:指的是JVM的错误,即此时的程序还没有执行而产生的异常即用户无法处理的异常;
Exception:指的是程序运行过程中产生的异常,用户可以处理的异常;
即:所谓的异常处理,指的就是所有Exception以及它的子类的异常
当程序在运行的过程中出现了异常之后,那么会有JVM自动根据异常的类型产生实例化一个与之类型匹配的异常类对象(系统自动处理,用户无需关系)
产生异常对象后,会判断当前的是否有异常处理语句,如果没有异常处理语句,那么就交给JVM进行默认的异常处理,处理的方式就是:输出异常信息而后中断程序执行。
如果此时有异常捕获操作,那么会有try语句来捕获产生的异常类实例化对象,而后有catch进行逐一比较并处理异常,执行逐一结束后,必须执行finally(无乱是否有异常)程序。
整个异常处理流程好似方法重载!
使用Exception进行异常catch匹配处理,而后在程序之中不用在担心是哪一种类型的异常;
异常捕获范围大的catch一定要放在捕获范围小的异常之后,否则程序编译报错;
虽然直接捕获Exception方便,但是并不好;因为所有的异常都会按照同样的一种方式进行处理;在一些严格的项目要求中,异常要分开处理;
throws关键字:
throws关键字主要用在方法声明上,指的是当方法之中出现异常后交由被调用处来进行处理;
class MyMath { //由于存在throws关键字 那么就表示此方法中产生的异常交给被调用处进行异常处理 public static int div(int x , int y) throws Exception { return x / y ; } }
public class TestDemo { public static void main(String [] args) { try { System.out.println(MyMath.div(10,2)) ; } catch (Exception e) { e.printStackTrace() ; } } } |
使用throws声明的方法之后,不管操作是否出现异常,都必须在调用处使用try…catch来进行异常处理(条件要求)
main主方法上也有了throws声明,则方法内调用处不用try处理throws的调用,因为调用抛出的异常处理,会由主方法抛给JVM默认处理。
原则上不建议在主方法上添加throws关键字,因为程序出错也希望正常的结束;所有的异常抛到主方法后,就不要在继续向JVM抛出异常了,否则程序就会中断执行。
throw关键字:
在程序中,可以直接用throw手工抛出一个异常类的实例化对象;
public class TestDemo { public static void main(String [] args) { try { throw new Exception ("自定义异常错误") ; // 抛出 自己实例化的异常类对象 } catch (Exception e) { e.printStackTrace() ; } } } |
throw和throws的区别:
throw:指的是在一个方法之中人为的抛出一个异常类对象(这个异常类可能是自己实例化的或者是已存在的)
throws:在方法的尾部声明使用,表示此方法会抛出一个异常交给调用处,在调用时必须try处理异常,有异常则处理,没有异常则正常执行。
代码模型:异常的使用格式——
要求定义一个div方法,要求该方法,在计算之前打印提示信息,在计算完毕也打印提示信息,如果在计算之中产生了异常则交给被调用处进行处理
class MyMath { public static int div(int x , int y) { int result = 0 ; System.out.println("******") ; result = x / y ; System.out.println("======") ; return result ; } }
public class TestDemo { public static void main(String [] args) { System.out.println(MyMath.div(10,2)) ; } } |
进行合理的异常处理后的Code:
class MyMath { public static int div(int x , int y) throws Exception { int result = 0 ; System.out.println("******") ; result = x / y ; System.out.println("======") ; return result ; } }
public class TestDemo { public static void main(String [] args) { try{ System.out.println(MyMath.div(10,2)) ; } catch (Exception e) { e.printStackTrace() ; } } } |
如果上例程序确实发生了异常,mymath类中的内容依旧无法执行结束;因为,一旦出现异常就会直接由throws抛给调用处;为此,则在方法内部设置try异常捕获
class MyMath { public static int div(int x , int y) throws Exception { int result = 0 ; System.out.println("******") ; try{ result = x / y ; } catch (Exception e) { throw e ; //由throw将异常对象e抛出 } finally { System.out.println("======") ; } return result ; } }
public class TestDemo { public static void main(String [] args) { try{ System.out.println(MyMath.div(10,0)) ; } catch (Exception e) { e.printStackTrace() ; } } } |
【待经验积累】
Runtime类:
Java为了方便用户代码的编写,专门提供了一种 RuntimeException类,这种异常类最大的特征在于:程序在编译的时候,不会强制性的要求用户处理异常,用户可以根据自己的需要选择性的处理,但如果没有处理,且发生异常了就交给JVM默认处理。也就是说RuntimeException异常类可以根据用户的需呀选择进行处理。
Exception与RuntimeException的区别:
Exception是RuntimeException的父类;Exception定义的异常必须要被处理,而RuntimeException的异常可以选择性的被处理。
Assert关键字:
主要功能则是:进行断言;在Java中的断言,指的是 程序执行到某行代码处时一定是预期的结果。
public class TestDemo { public static void main(String [] args) { int num = 10 ; // 中间经过处理,改变了num的内容 assert num == 20 : "num is not 20" ; System.out.println(num) ; } } |
上述代码,输出的结果是num的值;为什么?
默认情况下,断言是不影响程序的运行的,也就是说在Java解释程序的时候,断言是默认不起作用的。
而如果在运行的时候使用了 –ea 则会启动断言
在Java中,断言的设计高于C++中,但是使用的意义不大!!!
自定义异常:
Java本身提供的异常非常健全,但是系统的异常往往不足,故此需要自定义异常类:
开发自定义的异常类,可以选择继承Exception或者RuntimeException类
class AddException extends Exception { public AddException(String msg) { super (msg) ; } } public class TestDemo { public static void main(String [] args) { int num = 11 ; try{ if (num > 10) { throw new AddException("数值过大") ; } } catch (Exception e) { e.printStackTrace() ; } } }
|