java中的异常
程序在运行期发生的不正常的事件,它会打断指令的正常执行流程
异常的作用?
增强程序的健壮性。
Java语言使用异常处理机制为程序提供了异常处理能力
Java语言中异常是以什么形式存在的呢?
-
错误(Error)
JVM系统内部错误或资源耗尽等严重情况-属于JVM需要负担的责任,这一类异常事件无法恢复或不可能捕获,将导致应用程序中断。
-
异常(Exception)
其它因编程错误或偶然的外在因素导致的一般性问题。这类异常得到恰当的处理时,程序有机会恢复至正常运行状况
-
非受检(unchecked)异常(运行时异常 RuntimeException)
编译器不要求强制处置的异常。一般是指编程时的逻辑错误。是程序员应该积极避免其出现的异常
java.lang.RuntimeException及它的子类都是非受检异常:
-
错误的类型转换:java.lang.ClassCastException
-
数组下标越界:java.lang.ArrayIndexOutOfBoundsException
-
空指针访问:java.lang.NullPointerException
-
算术异常(除0溢出):java.lang.ArithmeticException
-
-
受检(checked)异常 --- 一般性异常(编译时异常 所有Exception直接子类)
编译器要求必须处置的异常。指的是程序在运行时由于外界因素造成的一般性异常。
由于外界因素造成的一般性异常:
-
没有找到指定名称的类:java.lang.ClassNotFoundException
-
访问不存在的文件:java.io.FileNotFoundException
-
操作文件时发生的异常:java.io.IOException
-
-
-
异常的处理机制
-
Java程序在执行过程中如果出现异常,会自动生成一个异常类对象,该异常对象将被自动提交给JVM,这个过程称为抛出(throw)异常
-
当JVM接收到异常对象时,会寻找能处理这一异常的代码并把当前异常对象交给其处理,这一过程称为捕获(catch)异常和处理异常
-
如果JVM找不到可以捕获异常的代码,则运行时系统将终止,相应的Java程序也将退出。
注解:所有异常都是发生在运行阶段的。
-
使用try...catch语句进行异常的捕捉
1 try{ 2 ...... //可能产生异常的代码 3 }catch( ExceptionName1 e ){ 4 ...... //异常的处理代码 5 }catch( ExceptionName2 e ){ 6 ...... //异常的处理代码 7 } finally{ 8 ...... //无论如何都会执行的语句 9 }
注解:
-
try 代码段包含的是可能产生异常的代码
-
1) try 代码段后跟一个或多个catch代码段。(或跟一个finally代码段)
-
当异常发生时,程序会中止当前的流程去执行相应的catch代码段
-
写catch代码时,先捕获的异常的范围不能大于后捕获的异常的范围。大的异常要写在后面
例如:
1 try{ 2 //...可能会报异常的代码 3 }catch(ClassNotFoundException e){//小的异常 4 e.printStackTrach();//catch括号里面可以是具体的类型异常,也可以是该异常类型的父类型异常 5 }catch(Exception e){//大的异常 6 e.printStackTrach(); 7 }
-
finally段的代码无论是否发生异常都执行
-
java 8新特性:一个catch代码可以可以声明多个能处理的特定异常的类型,多个类型之间用”|”隔开
例如:catch( ExceptionName1 | ExceptionName2 e){
...... //异常的处理代码
}
1 public static void main(String[] args){ 2 try { 3 method(); 4 } catch (ClassNotFoundException | FileNotFoundException e) { 5 e.printStackTrace(); 6 } 7 //这就是try...catch语句捕捉异常 8 } 9 public static void method() throws ClassNotFoundException,FileNotFoundException { 10 System.out.println("我是方法"); 11 }
-
-
throws抛出异常类型(类似于推卸责任)
在方法的位置上,使用throws关键字抛出异常,抛给上一级,谁调用就抛给谁,如果异常不处理继续往上抛,最终抛给main()方法,main()方法继续往上抛,抛给了JVM,JVM只有一个结果,使java程序终止
例如:
1 public static void main(String[] args) throws FileNotFoundException{ 2 m1();//最终抛给了JVM JVM终止程序 3 //一般main方法中的异常建议使用try..catch进行捕捉。 4 } 5 private static void m1() throws FileNotFoundException{ 6 m2();//throws 后面可以有多个异常 使用 “,” 隔开 7 } 8 private static void m2() throws FileNotFoundException{ 9 m3();//调用者可以抛被调用者异常的父类或者就抛被调用者异常,其他不行 10 } 11 12 private static void m3() throws FileNotFoundException{ 13 new FileInputStream("D:\\aaa.txt"); 14 System.out.println("以上代码出异常,这里不会执行"); 15 }
-
throw抛出单个具体异常对象(一般手动抛异常)
1 //异常不仅仅虚拟机可以抛,我们自己也可以抛。我们可以在代码中使用throw关键字(注意不带s)来抛出某个具体的异常对象。很多情况下我们会手动抛出运行时异常 2 throw new RuntimeException("程序出现了异常"); 3 //常常和自定义异常结合
-
throw和throws区别
-
throws用来声明一个方法可能会产生的异常或者异常类型,在方法体内不做任何处理,将异常往调用方抛
-
在方法声明后,跟上异常类型名,可以跟多个,异常名之间逗号隔开
-
throws抛出的异常是一种可能性,不一定会发生
-
throws抛出的可以是一个异常范围,也可以是具体的异常
-
-
throw用来抛出单个具体异常对象
-
用在方法体内,跟的是异常对象名
-
只能抛出一个异常对象
-
抛出的异常在方法体内处理
-
-
-
-
获取异常简单的描述信息:
String msg = exception.getMessage();
-
打印异常追踪的堆栈信息:
exception.printStackTrace();
例如:
1 public static void main(String[] args) { 2 //new一个异常 3 NullPointerException e = new NullPointerException("空指针异常"); 4 //new了一个异常 但是没抛出 所以下面的代码继续执行 不会中断程序 5 String msg = e.getMessage();//获取异常的信息 6 System.out.println(msg);//打印的就是 空指针异常 7 e.printStackTrace();//打印异常堆栈信息 底层有一个专门的线程负责这个事情的 8 //java后台打印异常堆栈追踪信息的时候,采用了异步线程的方式打印的。 9 }
注意:以后查看异常的追踪信息,从上往下一行一行看,但是需要注意的是:SUN写的代码就不用看了(看包名就知道是自己的还是SUN的。)。
例如:
1 public static void main(String[] args){ 2 try{ 3 System.out.println("try..."); 4 System.exit(); 5 }finally{ 6 System.out.println("finally..."); 7 } 8 }
1 public static void main(String[] args) { 2 int result = m(); 3 System.out.println(result); //返回的是100 4 } 5 6 public static int m(){ 7 int i = 100; 8 try { 9 // 这行代码出现在int i = 100;的下面,所以最终结果必须是返回100 10 // return语句还必须保证是最后执行的。一旦执行,整个方法结束。 11 return i; 12 } finally { 13 i++;//这行代码执行了 14 } 15 } 16 17 //反编译底层源码 18 public static int m(){ 19 int i = 100; 20 int j = i; 21 i++; 22 return j; 23 } 24 /** 25 JVM规范里面明确说明了这种情况: 26 大意就是如果在try中return的情况下,先把try中将要return的值先存到一个本地变量中,即本例中的i=100将会被保存下来。接下来去执行finally语句,最后返回的是存在本地变量中的值,即返i=100. 27 28 还有一点要注意的,如果你在finally里也用了return语句,比如return ++i。那么程序返回值会是101。因为规范规定了,当try和finally里都有return时,会忽略try的return,而使用finally的return。 29 */ 30 //总结:1、try中有return, 会先将值暂存,无论finally语句中对该值做什么处理,最终返回的都是try语句中的暂存值。 2、当try与finally语句中均有return语句,会忽略try中return。
Java语句中的规则:
-
方法体中的代码必须遵循自上而下顺序依次逐行执行(亘古不变的语法!)
-
return语句一旦执行,整个方法必须结束(亘古不变的语法!)