1、异常的基本概念
异常:就是在程序运行过程产生的错误,它会中断正在运行的程序。
Java异常是Java提供的用于处理程序中错误的一种机制。所谓错误是指在程序运行的过程中发生的一些异常事件(如:除0溢出,数组下标越界,所要读取的文件不存在)。
设计良好的程序应该在异常发生时提供处理这些错误的方法,使得程序不会因为异常的发生而阻断或产生不可预见的结果。
Java程序的执行过程中如出现异常事件,可以生成一个异常类对象,该异常对象封装了异常事件的信息并将被提交给Java运行时系统,这个过程称为抛出(throw)异常。
当Java运行时系统接收到异常对象时,会寻找能处理这一异常的代码并把当前异常对象交给其处理,这一过程称为捕获(catch)异常。
public class Test { public static void main(String[] args) { String friends [] ={ "Tom","John","Jenni" }; for (int i = 0;i < 4;i++){ System.out.println(friends[i]);. } } }
🌻在Java之中如果要进行异常的处理,可以使用:try、catch、finally这几个关键字来完成,其基本的处理结构如下:
try{ //可能出现异常的语句 }[catch(异常类型 异常对象){ //异常处理 }catch(异常类型 异常对象){ //异常处理 }catch(异常类型 异常对象){ //异常处理 }.....] [finally { 不管异常是否处理都要执行 ; }]
🌻处理异常
public class Demo{ public static void main(String args[]) { System.out.println("【1】*****程序开始执行*****") ; try { System.out.println("【2】数学计算:" +(10 / 0)) ; } catch (ArithmeticException e) { System.out.println("【c】处理异常:" + e) ; //处理异常 } System.out.println("【3】*****程序执行完毕*****") ; } }
此时可以发现现在即便出现了异常,程序也可以正常执行完毕,所以此时的设计属于一个合理设计。但是有一个问题出现了,此时在进行异常处理的时候直接输出的是一个异常类的对象,那么对于此对象如果直接打印(调用toString())所得到的异常信息并不完整,如果要想获得非常完整的异常信息,则可以使用异常类中提供的printStackTrace()方法完成。
对于异常的处理格式也可以在最后追加有一个finally的程序块,表示异常处理后的出口,不管是否出现异常都执行。
🌻范例:使用finally语句
public class Demo{ public static void main(String args[]) { System.out.println("【1】*****程序开始执行*****") ; try { System.out.println("【2】数学计算:" +(10 / 0)) ; } catch (ArithmeticException e) { e.printStackTrace() ; }finally { System.out.println("【F】不管是否出现异常,我都会执行。") ; } System.out.println("【3】*****程序执行完毕*****") ; } } 此时程序中有异常执行finally,没有异常也执行finally。
🌻在整个Java的异常处理中,实际上也是按照面向对象的方式进行处理,处理的步骤如下:
(1)一旦产生异常,则首先会产生一个异常类的实例化对象。
(2)在try语句中对此异常对象进行捕捉。
(3)产生的异常对象与catch语句中的各个异常类型进行匹配,如果匹配成功,则执行catch语句中的代码。
2、throws与throw关键字
(1)throws关键字
在定义一个方法时可以使用throws关键字声明,使用throws声明的方法表示此方法不处理异常,而交给方法的调用处进行处理。
🌻throws使用格式如下:
public 返回值类型 方法名称(参数列表···)throws 异常类{ }
🌻范例:使用throws关键字处理异常
class Math { public int div (int i,int j ) throws Exception { //方法可以不处理异常 int temp=i/j; return temp; } } public class ThrowsDemo{ public static void main(String[] args){ Math m=new Math(); try{ //因为有throws,不管是否有异常,都必须处理 System.out.println("除法操作:"+m.div(10,2)); }catch(Exception e){ e.printStackTrace(); } } }
🌻运行结果:
除法操作:5
主方法也可以使用throws关键字,但是主方法是程序的起点,所以此时主方法再向上抛异常,则只能将异常抛给JVM进行处理。
class Math { public int div (int i,int j ) throws Exception { //方法可以不处理异常 int temp=i/j; return temp; } } public class ThrowsDemo2{ //本方法中的所有异常都可以不使用try catch处理的 public static void main(String[] args) throws Exception { Math m=new Math(); System.out.println("除法操作:"+m.div(10,2)); } }
🌻运行结果:
除法操作:5
(2)throw关键字
与throws不同的是,可以直接使用throw抛出一个异常,抛出时直接抛出异常类的实例化对象即可。
🌻范例:
public class ThrowDemo{ public static void main (String[] args){ try{ throw new Exception("自己抛出的异常!") }catch(Exception e) { System.out.println(e); } }
异常产生时肯定会由系统产生一个异常类的实例化对象,只是此时异常类的实例化对象是手工产生的。
(3)范例throw与throws的应用
try···catch···finally、throw、throws联合使用
🌻范例:
class Math{ public int div(int i,int j) throws Exception{ System.out.println("计算开始。"); int temp=0; try{ temp=i/j; }catch(Exception e){ throws e; }finally{ System.out.println("计算结束。"); } return temp; } } public class ThrowDemo2{ public static void main(String[] args){ Math m=new Math(); try{ System.out.println("除法操作:"+m.div(10,2)); }catch(Exception e){ System.out.println("异常产生:"+e); } } }
🌻运行结果:
计算开始。 计算结束。 异常产生:Dava.lang.ArithmeticException: / by zero
具体执行流程图:
3、Exception类与RuntimeException类
对于这个将字符串变为int类型的代码:int temp=Integer.parseInt(str);
Integer因为开头首字母大写,所以肯定是一个类,而parseInt()方法可以直接由类名称调用,所以此方法肯定是一个静态方法,此方法定义如下:
public static int parseInt (String s) throws NumberFormatException;
观察NumberFormatException类的继承关系:
🌻NumberFormatException属于RuntimeException的子类,那么这时就可以清楚地知道以下概念:
Exception在程序中必须使用try···catch进行处理。
RuntimeException可以不使用try···catch进行处理,但是如果有异常产生,则异常将由JVM进行处理。
4、自定义异常类
在Java中已经提供了大量的异常类,但是这些异常类有时也很难满足开发者的要求,所以用户可以根据自己的需要定义自己的异常类。定义异常类只需要继承Exception类即可。
🌻范例:
class MyException extends Exception{// 自定义异常类 public MyException(String msg){ super(msg); } } public class Demo{ public static void main(String[] args){ try{ throws new MyException("自定义异常。");//抛出异常 }catch(Exception e){//异常处理 System.out.println(e); } } }
🌻运行结果:
MyException:自定义异常。
5、断言
在JDK 1.4之后,Java中增加了断言的功能。断言就是肯定某一个结果的返回值是正确的,如果最终此结果的返回值是错误的,则通过断言检查肯定会提示错误信息。
🌻断言的定义格式如下:
assert boolean 表达式; assert boolean 表达式:详细的信息
如果以上boolean表达式的结果为frue,则什么错误信息都不会提示;如果为false,则会提示错误信息;如果没有声明详细信的描述,则系统会使用默认的错误信息提示方式。
🌻范例:
public class Demo{ public static void main(String[] args){ int x[]={1,2,3}; assert x.length==0;//此处使用断言,结果为false } }
此处的断言结果是错误的,但此时运行程序并不会得到任何的结果,这是因为Java在设计此关键字时,考虑到了系统的应用,为了防止某些用户使用assert作为关键字,所以在程序正常运行时断言并不会起任何的作用.
如果要想让断言起作用,则在使用Java运行时应该加入参数:—enableassertions 也可以简写为-ea
🌻运行程序格式如下:
编译程序:javac Demo.java 验证程序:java -ea Test
🌻程序运行时出现以下错误:
Exception in thread “main” Java. lang.AssertionError at Test.main(Demo.java:4)
注意断言的使用:
(1)虽然断言返回的是boolean值,但是并不能将其作为条件判断语句。
(2)断言虽然有检查运行结果的功能,但是一般在开发中并不提倡使用断言。