欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Java核心编程之异常的捕获及处理

程序员文章站 2022-04-01 11:29:15
...

前言

本篇文章笔者准备重点介绍异常的产生原理,异常处理的基本格式,throw和throws关键字的作用,自定义异常,以及Exception与RuntimeException的区别,断言的作用等等

异常的基本概念

异常是导致程序中断运行的一种指令流,如果不对异常进行正确的处理,则可能导致程序的中断执行,造成不必要的损失,所以在程序的设计中必须要考虑各种异常的发生,并正确做好相应的处理,这样才能保证程序的正常运行。在Java中一切异常都秉着面向对象的设计思想,所有的异常都以类和对象的形式存在,除了Java中已经提供的各种异常类外,用户也可以根据需要定义自己的异常类。

为什么需要异常处理

在没有异常处理的语言中如果要回避异常,就必须使用大量的判断语句,配合所想到的错误状况来捕捉程序中所有可能发生的错误。但为了捕捉这些错误,编写出来的程序代码经常有大量的判断语句,又是这样也未必能捕捉到所有的错误,而且这样做势必导致程序的运行效率的降低。

Java的异常处理机制恰好改进这一点。它具有易于使用,可自行定义异常类,处理抛出的异常同时又不会降低程序运行的速度等优点。因在Java程序设计时,应充分利用Java的异常处理机制,以增进程序的稳定性及效率。

认识异常

public class ExceptionDemo01{
public static void main(String[] args){
System.out.println(******计算开始*******);
int i=10;
int j=0;
int temp=i/j;
System.out.print("两个数字相除结果:" +temp);
System.out.print(******计算结果*******);
}
}

程序运行结果:

计算开始
Exception in thread”main”java.lang.ArithmeticException:/by zero at ExceptionDemo01.main(ExceptionDemo01.java:6 )

在以上程序中,因为被除数为0,所以程序中出现异常,从运行结果可以发现,如果不对异常进行处理,则一旦出现异常后,程序立刻退出,所以后面的两条语句并没有打印输出。此程序的执行流程如图所示
Java核心编程之异常的捕获及处理

解决方案

在程序中进行异常处理

Java核心编程之异常的捕获及处理

范例

public class ExceptionDemo02{
public static void main(String[] args){
System.out.println("*****计算开始*****");
int i=10;
int j=0;
try{
int temp=i/j;
System.out.println("两个数字相除的结果:"+temp);
System.out.println("------------");
}catch(ArithmeticException e ){
System.out.println("出现异常了" +e);
}
System.out.println("*******计算结束*******");
}
}

程序运行结果:

计算开始
出现异常了:java.lang.ArithmeticException:/by zero
计算结束

Java核心编程之异常的捕获及处理

从图中可以清楚的看到,所有异常都在catch中处理了,catch处理完毕之后,程序正常结束。实际上在异常处理的最后有一个finally关键字,可以使用它作为异常的统一接口。

验证finally关键字

public class ExceptionDemo03{
public static void main(String[] args){
System.out.print("******计算开始******");
int i=10;
int j=0;
try{
int temp=i/j;
System.out.println("两个数字相除结果:"+temp);
System.out.println("---------");
}catch(ArithmeticException e){
System.out.println("出现异常了:" +e);
}finally{
System.out.println("不管是否出现异常,都执行代码");
}
System.out.println(******计算结束*****);

程序运行结果:

计算开始
出现异常了:java.lang.ArithmeticException:/byzero
不管是否出现异常,都执行此代码
计算结束

通常程序开发中不会只有一个异常,肯定同时存在多个异常,此时就需要了解异常类的继承结构

Java核心编程之异常的捕获及处理

  • Exception:一般表示的是程序中出现的问题,可以直接使用try….catch处理。
  • Error:一般指的是JVM错误,程序中无法处理。
  • 一般情况下,开发者习惯于将Exception和Error统称为异常,而算术异常,数字格式异常等都属于Exception的子类。

Java异常信息的输出方式

  • System.out.println(异常对象)
  • e.printStackTrace()

Java的异常处理机制

在整个Java的异常处理中,实际上也是按照面向对象的方式进行处理,处理的步骤如下:
(1) 一旦产生异常,则首先会产生一个异常类的实例化对象。
(2)在try语句中对此异常类进行捕捉
(3)产生的异常对象与catch语句的各个异常类型进行匹配,如果匹配成功,则执行catch语句中的代码。
Java核心编程之异常的捕获及处理

从之前学习过的对象多态性可以清楚的知道,所有的子类实例可以全部使用父类类型接收,那么就可以利用向上转型的概念,让所有的异常对象都使用Exception接收。

范例

public class ExceptionDemo{
public static void main(String[] args){
System.out.println(********计算开始*******);
int i=0;
int j=0;
try{
String str1=args[0];
String str2=arg[1];
i=Integer.parseInt(str1);
j=Integer.parseInt(str2);
int temp=i/j;
System.out.println("两个数字相除的结果:"+temp);
System.out.println("--------------");
}catch(Exception e){
System.out.println("其它异常:" +e);
}
System.out.println(*******计算结束*******);
 }
} 

以上代码直接使用Exception进行异常处理,所以任何的异常都可以非常方便地进行处理。

throws与throw关键字

throws关键字

在定义一个方法时可以使用throws关键字声明,使用throws声明的方法表示此方法不处理异常,而交给方法的调用处进行处理。

范例:处理异常

class Math{
public int div(int i,int j)throws Exception{ //本方法不处理异常
int temp=i/j;
return temp;
}
}
public class ThrowsDemo01{
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


以上代码中,不管是否有问题,都要使用try…catch块进行异常的捕获与处理。既然throws是在方法处定义的,那么在主方法中也可以使用throws关键字,但是主方法为程序的起点,所以此时主方法再向上抛异常,则只能将异常抛给JVM进行处理。这就好比一个公司,部门事情处理不了,要上报给经理,经理再解决不了要上报给董事长,到董事长了,也就到头了,那么Java的头就是JVM。

范例:主方法处使用throws关键字

class Math{
public int div(int i, int j)throws Exception{
int temp=i/j;
return temp;
}
}
public class ThrowsDemo{
//本方法中所有的异常都可以不使用try....catch处理的
public static void main(String[] args){
Math m=new Math();
System.out.println("除法操作:"+m.div(102));
}
}

以上代码在主方法处使用了throws关键字,所以在程序主方法中就可以不再使用try…catch语句进行异常的捕获及处理。

提醒

主方法为一切的起点,一切的操作也都是由主方法开始的。所以如果在主方法中使用throws,则程序出现问题后肯定交由JVM进行处理,将导致程序中断。

throw关键字

与throws关键字不同的是,可以直接使用throw关键字人为地抛出一个异常,抛出时直接抛出异常类的实例化对象即可。

范例:抛出异常

public class ThrowDemo01{
public static void main(String[] args){
try{
throw new Exception("自己抛出的异常!");//抛出异常的实例化对象
}catch(Exception e){
System.out.println(e);
}
}
}

程序运行结果:

java.lang.Exception:自己抛出的异常!

throw与throws的综合运用

class Math{
public int div(int i, int j)throws Exception{  //方法不可以处理异常
System.out.println("******计算开始*******");
int temp=0;
try{
temp=i/j;
}cath(Exception e){
throw e  //把异常交给被调用处
}finally{ 
System.out.println("******计算结束*****");
}
return temp;
}
}
public class ThrowDemo{
public static void main(String[] args){
Math m = new Math();
try{
System.out.println("除法操作:"+m.div(10,0));
}catch(Exception e){
System.out.println("异常产生:"+e);
}
}
}

程序运行结果:

计算开始
计算结束
异常产生:java.lang.ArithmeticException:/by zero

Exception类与RuntimeException类的区别

Java核心编程之异常的捕获及处理

自定义异常类

在Java中已经提供了大量的异常类,但是这些异常类有时也很难满足开发者的需要,所以用户可以根据自己的需要来定义自己的异常类。定义自己的异常类只需要继承Exception类即可

范例:

class MyException extends Exception{ //自定义异常类,继承Exception类
public MyException(String msg){
super(msg);
}
}
public class DefaultException{
public static void main(String[] args){
try{
    throw new MyException("自定义异常。");
    }catch(Exception e){
    System.out.println(e);
    }
 }
}    

程序运行结果:

MyException:自定义异常。

断言

在JDK1.4之后,Java中增加了断言的功能。断言就是肯定某一结果的返回值是正确的,如果最终此结果的返回值是错误的,则通过断言检查肯定会提示错误信息。

范例:

public class Test{
public static void main(String[] args){
int x[]={1,2,3}
assert x.length==0;
}
}

以上程序中,数组x的长度是不可能为0的,所以,此处的断言结果是错误的,但此时运行程序并不会得到任何的结果,因为Java在设计assert关键字时考虑到系统的应用。
如果要想让断言起作用,可以使用一下参数运行参数
编译程序: javacTest.java
验证程序:java -ea Test

程序运行结果:

Exception in thread “main”java.lang.AssertionError at Test.main(Test.java:4)

以上出现的是断言错误,因为数组x的长度不可能是0,所以验证结果就出现了问题。

总结

以上就是笔者对异常的一点理解,有什么不足,请多多指教!