java异常处理(较详细)
在使⽤计算机语⾔进⾏项⽬开发的过程中,即使程序员把代码写得尽善尽美,在系统的运⾏过程中仍然会遇到⼀些问题,因为很多问题不是靠代码能够避免的。
⽐如: 客户输⼊数据的格式, 读取⽂件是否存在, ⽹络是否始终保持通畅等等。
异常:在语⾔中, 将程序执⾏中发⽣的不正常情况称为“异常” 。
(开发过程中的语法错误和逻辑错误不是异常)
Java程序在执⾏过程中所发⽣的异常事件可分为两类:
Error: Java虚拟机⽆法解决的严重问题。 如: JVM系统内部错误、 资源耗尽等严重情况。
⽐如: StackOverflowError和OOM。 ⼀般不编写针对性的代码进⾏处理。
Exception: 其它因编程错误或偶然的外在因素导致的⼀般性问题, 可以使⽤针对性的代码进⾏处理。 例如:
1、空指针访问
2、试图读取不存在的⽂件
3、⽹络连接中断
4、数组⾓标越界
对于这些错误, ⼀般有两种解决⽅法:
⼀种是遇到错误就终⽌程序的运⾏。
⼀种⽅法是由程序员在编写程序时, 就考虑到错误的检测、 错误消息的提⽰, 以及错误的处理。
捕获错误最理想的是在编译期间, 但有的错误只有在运⾏时才会发⽣。
⽐如: 除数为0, 数组下标越界等
分类: 编译时异常和运⾏时异常
1.运⾏时异常
是指编译器不要求强制处置的异常。⼀般是指编程时的逻辑错误,是程序员应该积极避免其出现的异常。 java.lang.RuntimeException类及它的⼦类都是运⾏时异常。
对于这类异常,可以不作处理,因为这类异常很普遍,若全处理可能会对程序的可读性和运⾏效率产⽣影响。
2.编译时异常
是指编译器要求必须处置的异常。即程序在运⾏时由于外界因素造成的⼀般性异常。
编译器要求Java程序必须捕获或声明所有编译时异常。
对于这类异常,如果程序不处理,可能会带来意想不到的结果。
机制⼀:try-catch-finally
在编写程序时,经常要在可能出现错误的地⽅加上检测的代码,
如进⾏x/y运算时,要检测分母为0,数据为空,输⼊的不是数据⽽是字符等。
过多的if-else分⽀会导致程序的代码加长、臃肿,可读性差。因此采⽤异常处理机制。
Java异常处理
Java采⽤的异常处理机制,是将异常处理的程序代码集中在⼀起,与正常的程序代码分开,
使得程序简洁、优雅, 并易于维护。
java异常处理的⽅式:
⽅式⼀: try-catch-finally
⽅式⼆: throws + 异常类型
Java提供的是异常处理的抓抛模型。
过程⼀:Java程序的执⾏过程中如出现异常, 会⽣成⼀个异常类对象,该异常对象将被提交给Java运⾏时系统, 这个过程称为抛出(throw)异常。
过程⼆:抓,可以理解为异常的护理⽅式。
异常对象的⽣成
由虚拟机⾃动⽣成:程序运⾏过程中,虚拟机检测到程序发⽣了问题,如果在当前代码中没有到相应的处理程序,就会在后台⾃动创建⼀个对应异常类的实例对象并抛出——⾃动抛出
由开发⼈员⼿动创建: Exception exception = new ClassCastException();——创建好的异常对象不抛
出对程序没有任何影响,和创建⼀个普通对象⼀样。
如果⼀个⽅法内抛出异常, 该异常对象会被抛给调⽤者⽅法中处理。
如果异常没有在调⽤者⽅法中处理, 它继续被抛给这个调⽤⽅法的上层⽅法。
这个过程将⼀直继续下去, 直到异常被处理。这⼀过程称为捕获(catch)异常。
如果⼀个异常回到main()⽅法, 并且main()也不处理, 则程序运⾏终⽌。
程序员通常只能处理Exception, ⽽对Error⽆能为⼒。
异常处理是通过try-catch-finally语句实现的。
try 捕获异常的第⼀步是⽤try{…}语句块选定捕获异常的范围, 将可能出现异常的代码放在try语句块中。在执⾏过程中,⼀旦出现异常,就会⽣成⼀个对应异常类的对象,根据此对象的类型,去catch中进⾏匹配。 ⼀旦try中的异常对象匹配到某⼀个catch时,就进⼊catch中进⾏异常处理,⼀旦处理完成就跳出当前的try-catch结构(在没有写finally的情况下)。继续执⾏其后的代码。在try结构中声明的变量,出了try结构之后,就不能被调⽤。
catch (Exceptiontype e)
在catch语句块中是对异常对象进⾏处理的代码。 每个try语句块可以伴随⼀个或多个catch语句, ⽤于处理可能产⽣的不同类型的异常对象。catch中的异常类型如果没有⼦⽗类关系,则谁声明在上,谁声明在下⽆所谓,如果异常类型满⾜⼦⽗类的关系,则要求⼦类⼀定要声明在⽗类的上⾯,否则报错。
finally
捕获异常的最后⼀步是通过finally语句为异常处理提供⼀个统⼀的出⼝,使得在控制流转到程序的其它部分以前,能够对程序的状态作统⼀的管理。
不论在try代码块中是否发⽣了异常事件, catch语句是否执⾏, catch语句是否有异常, catch语句中是否有return,finally块中的语句都会被执⾏。
finaly中声明的是⼀定会被执⾏的代码,即使catch中出现了异常,try中有return语句,catch中有return语句等情况。
finally语句和catch语句是任选的。
像数据库连接,输⼊输出流,⽹络编程socket等资源,JVM是不能⾃动回收的,我们需要⼿动的进⾏资源的释放。此时的资源的释放,就需要声明在finally中。
注意:
如果明确知道产⽣的是何种异常, 可以⽤该异常类作为catch的参数;也可以⽤其⽗类作为catch的参数。
⽐ 如 : 可 以 ⽤ ArithmeticException 类 作 为 参 数 的 地 ⽅ , 就 可 以 ⽤RuntimeException类作为参数, 或者⽤所有异常的⽗类Exception类作为参数。但不能是与ArithmeticException类⽆关的异常, 如NullPointerException(catch中的语句将不会执⾏) 。使⽤try-cathch-finally处理编译时异常,使得程序在编译时不在报错,但在运⾏时,仍有可能报错。相当我们使⽤try-catch-finally将⼀个编译时可能出现的异常,延迟到运⾏时出现。
try-catch-finally结构可以相互嵌套。
捕获异常的有关信息:
与其它对象⼀样,可以访问⼀个异常对象的成员变量或调⽤它的⽅法。
getMessage() 获取异常信息,返回字符串
printStackTrace() 获取异常类名和异常信息,以及异常出现在程序中的位置。返回值void。
不捕获异常时的情况
前⾯使⽤的异常都是RuntimeException类或是它的⼦类,这些类的异常的特点是:即使没有使⽤try和catch捕获, Java⾃⼰也能捕获,并且编译通过( 但运⾏时会发⽣异常使得程序运⾏终⽌ )。
如果抛出的异常是IOException等类型的⾮运⾏时异常,则必须捕获,否则编译错误。也就是说,我们必须处理编译时异常,将异常进⾏捕捉,转化为运⾏时异常。
异常处理机制⼆:throws +异常类型
声明抛出异常是Java中处理异常的第⼆种⽅式
throws +异常类型,写在⽅法的声明处,此时此⽅法执⾏时, 可能会抛出的类型。
如果⼀个⽅法(中的语句执⾏时)可能⽣成某种异常, 但是并不能确定如何处理这种异常, 则此⽅法应显⽰地声明抛出异常,表明该⽅法将不对这些异常进⾏处理,⽽由该⽅法的调⽤者负责处理。
try catch的使用方法在⽅法声明中⽤throws语句可以声明抛出异常的列表, throws后⾯的异常类型可以是⽅法中产⽣的异常类型, 也可以是它的⽗类。
⼀旦⽅法体执⾏时,出现异常,仍会在异常代码处,⽣成⼀个异常类的对象,此对象满⾜throws后异常类型是,就会被抛出。异常代码后续的代码,就不在执⾏。
throws的⽅式只是将异常抛给了⽅法的调⽤者,并没有真正将异常处理掉。
声明抛出异常举例:
public void readFile(String file) throws FileNotFoundException {undefined ……
/
/ 读⽂件的操作可能产⽣FileNotFoundException类型的异常
FileInputStream fis = new FileInputStream(file);
………
}    public  void  method () {          try  {              test3();          } catch  (FileNotFoundException e ) {              e .printStackTrace ();          } catch  (IOException e ) {              e .printStackTrace ();          }    }          @Test      public  void  test3() throws  FileNotFoundException ,IOException {          File file =new  File ("");          FileInputStream fis = new  FileInputStream (file );                    int  data = fis .read ();          while (data != -1) {              System .out .println ((char )data );              data = fis .read ();          }          fis .close ();    }}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
重写⽅法声明抛出异常的原则
重写⽅法不能抛出⽐被重写⽅法范围更⼤的异常类型。 在多态的情况下,
对methodA()⽅法的调⽤-异常的捕获按⽗类声明的异常处理。
如何选择try-catch和throws
如果⽗类中被重写的⽅法中没有throws⽅式处理异常,则⼦类重写的⽅法中也不能使⽤throws,意味如果⼦类重写的⽅法中有异常,必须使⽤try-catch。
执⾏的⽅法a中,先后⼜调⽤了另外的⼏个⽅法,这九个⽅法是递进关系执⾏的,我们建议这⼏个⽅法使⽤throws的⽅式进⾏处理。⽽执⾏的⽅法a可以考虑使⽤try-catch
⼿动抛出异常
java异常类对象除在程序执⾏过程中出现异常时由系统⾃动⽣成并抛出, 也可根据需要使⽤⼈⼯创建并抛出。
⾸先要⽣成异常类对象, 然后通过throw语句实现抛出操作(提交给Java运⾏环境)。
IOException e = new IOException();
throw e;
可以抛出的异常必须是Throwable或其⼦类的实例。 下⾯的语句在编译时将会产⽣语法错误:
throw new String(“want to throw”);public  class  A {public  void  methodA () throws  IOException {……} }public  class  B1 extends  A {public  void  methodA () throws  FileNotFoundException {……} }public  class  B2 extends  A {public  void  methodA () throws  Exception { //报错……} }
1
2
3
4
5
6
7
8
9
10
11
12
13

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。