A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

在正常的程序设计中,程序异常处理是非常关键和重要的一部分。试想一个项目中没有一个好的异常处理,这个项目会怎么样?

什么是异常

异常其实是程序上的错误,包括程序逻辑错误和系统错误。比如数组下标越界、内存溢出等,这些都是意外的情况,错误在我们的程序的编写过程中会经常发生,包括编译期间和运行期间的错误。在编译期间出现的错误编译器会帮助我们修正,可是在运行期间的错误编译器就无能为力了,并且运行期间的错误往往是难以预料的。

程序出现了错误,我们不能不去处理,这样的程序的健壮性太差了。为了提高程序的健壮性我们要合理的解决这些错误!于是Java中提供了异常的处理机制,通过异常来处理程序运行期间中出现的错误。通过这一特性,我们可以很好的提高程序的健壮性。

Java是一个全面的面向对象语言,不像PHP那样,既支持过程式编程,也支持面向对象编程。Java中异常的父类是java.lang.Throwable类。在Java中定义很多的的异常类,比如OutOfMenoryError、NullPointerException、IndexOutOfBoundsException等。

Exception 类的层次

所有的异常类是从 java.lang.Exception 类继承的子类。

  • Exception 类是 Throwable类的子类。除了Exception类外,Throwable还有一个子类Error 。
    Java 程序通常不捕获错误。错误一般发生在严重故障时,它们在Java程序处理的范畴之外。
  • Error 用来指示运行时环境发生的错误。
    例如,JVM 内存溢出。一般地,程序不会从错误中恢复。

异常类有两个主要的子类:IOException 类和 RuntimeException 类。

Exception,也就是我们经常见到的一些异常情况,例如NullPointerException、IndexOutOfBoundsException等,这些异常时是我们可以处理的异常。

Exception类的异常包括checked exception和unchecked exception(unchecked exception也称作运行时异常RuntimeException,Exception类的异常都是在运行期间发生的),对于运行时异常,Java编译器不要求必须进行异常处理捕获处理或者抛出,这个由程序员自行决定。

checked exception(检查异常),也称为非运行时异常(运行时异常以外的异常就是非运行时异常),Java编译器强制程序员必须捕获处理,比如常见的IOException和SQLException。对于非运行时异常如果不进行捕获或者抛出处理,Java编译器都不会通过。

在网上找了一个图,能够很清楚的描述在Java中,异常类的结构层次。


在Java中,所有的异常都是继承至java.lang.Throwable类。Error类是error类型异常的父类,Exception类是exception类型异常的父类,RuntimeException类是所有运行时异常的父类,RuntimeException以外的并且继承Exception的类是非运行时异常。

  • 典型的RuntimeException包括NullPointerException、IndexOutOfBoundsException、IllegalArgumentException等。
  • 典型的非RuntimeException包括IOException、SQLException等。
Java如何处理异常

在Java中如果需要处理异常,必须先对异常进行捕获(这一点是和PHP是相同的)。使用try和catch关键字进行处理。具体的规则如下:



  • try{



  •   // 程序代码



  • }catch(异常类型1 异常的变量名1){



  •   // 程序代码



  • }catch(异常类型2 异常的变量名2){



  •   // 程序代码



  • }finally{



  •   // 程序代码



  • }


来段实际的代码:



  • import java.io.*;



  • public class ExcepTest{







  •    public static void main(String args[){



  •     try {



  •      File file = new File("/Users/sam/a.txt");



  •      if(!file.exists())



  •        file.createNewFile();



  •     } catch (IOException e) {



  •        e.printStackTrace();



  •     }



  •    }



  • }


被try块包围的代码说明这段代码可能会发生异常,一旦发生异常,异常便会被catch捕获到,然后需要在catch块中进行异常处理。这是一种处理异常的方式。在Java中还提供了另一种异常处理方式即抛出异常,顾名思义,也就是说一旦发生异常,我把这个异常抛出去,让调用者去进行处理,自己不进行具体的处理,此时需要用到throw和throws关键字。

我们看下面的代码:



  • public class Main {



  •    public static void main(String[ args) {



  •        try {



  •            createFile();



  •        } catch (Exception e) {



  •            // TODO: handle exception



  •        }



  •    }



  •    



  •    public static void createFile() throws IOException{



  •        File file = new File("/Users/sam/a.txt);



  •        if(!file.exists())



  •            file.createNewFile();



  •    }



  • }


这段代码和上面一段代码的区别是,在实际的createFile方法中并没有捕获异常,而是用throws关键字声明抛出异常,即告知调用者此方法可能会抛出IOException,需要调用者进行捕获处理。那么在main方法中调用createFile方法的时候,采用try...catch块进行了异常捕获处理。

还可以使用throw关键字进行抛出异常。看下面的例子:



  • package exception;







  • /**



  • * Created by Sam on 18/6/17.



  • */



  • public class Main {







  •     public static void main(String[ args){



  •         People people = new People("Sam",new Byte("25"));



  •         people.sayAge();



  •     }



  • }











  • class People {







  •     private String name;



  •     private Byte age;







  •     public People(String name, Byte age) {



  •         this.name = name;



  •         this.age = age;



  •     }







  •     public String getName() {



  •         return name;



  •     }







  •     public void setName(String name) {



  •         this.name = name;



  •     }







  •     public Byte getAge() {



  •         return age;



  •     }







  •     public void setAge(Byte age) {



  •         this.age = age;



  •     }







  •     public Byte sayAge(){



  •         if (age > Byte.MIN_VALUE){



  •             throw new MyException("年龄太大了","100" );



  •         }



  •         return age;



  •     }



  • }











  • public class MyException extends RuntimeException {







  •     private String code;







  •     public MyException(String message, String code) {



  •         super(message);



  •         this.code = code;



  •     }







  •     public String getCode() {



  •         return code;



  •     }







  •     public void setCode(String code) {



  •         this.code = code;



  •     }



  • }


上面就是利用throw关键字进行手动抛出异常。调用者可以捕获处理异常,也可以不用处理异常。下面我们就修改一下代码进行捕获处理:



  • public class Main {







  •     public static void main(String[ args){



  •         People people = new People("Sam",new Byte("25"));



  •         try {



  •             people.sayAge();



  •         }catch (Exception e){



  •             System.out.println(e);



  •         }







  •     }



  • }



  • 程序输出:



  • exception.MyException: 年龄太大了


也就说在Java中进行异常处理的话,对于可能会发生异常的代码,可以选择三种方法来进行异常处理:

1、对代码块用try..catch进行异常捕获处理;

2、在该代码的方法体外用throws进行抛出声明,告知此方法的调用者这段代码可能会出现这些异常,你需要谨慎处理。此时有两种情况:

如果声明抛出的异常是非运行时异常,此方法的调用者必须显示地用try..catch块进行捕获或者继续向上层抛出异常。

如果声明抛出的异常是运行时异常,此方法的调用者可以选择地进行异常捕获处理。

3、在代码块用throw手动抛出一个异常对象,此时也有两种情况,跟2)中的类似:

如果抛出的异常对象是非运行时异常,此方法的调用者必须显示地用try..catch块进行捕获或者继续向上层抛出异常。

如果抛出的异常对象是运行时异常,此方法的调用者可以选择地进行异常捕获处理。(如果最终将异常抛给main方法,则相当于交给jvm自动处理,此时jvm会简单地打印异常信息)

关于Java的异常机制就暂时说到这里。

【转载】原文地址:https://blog.csdn.net/qijingwang/article/details/80864872


2 个回复

倒序浏览
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马