【JavaSE】异常机制

异常指程序运行过程中出现的非正常现象,例如用户输入错误、除数为零、需要处理的 文件不存在、数组下标越界等。
所谓异常处理,就是指程序在出现问题时依然可以正确的执行完。
Java 是采用面向对象的方式来处理异常的。处理过程:

  • 抛出异常:在执行一个方法时,如果发生异常,则这个方法生成代表该异常的一个 对象,停止当前执行路径,并把异常对象提交给 JRE。
  • 捕获异常:JRE 得到该异常后,寻找相应的代码来处理该异常。JRE 在方法的调用 栈中查找,从生成异常的方法开始回溯,直到找到相应的异常处理代码为止。

一、异常分类

Java 对异常进行了分类,不同类型的异常分别用不同的 Java 类表示,所有异常的根类 为 java.lang.Throwable,Throwable 下面又派生了两个子类:Error 和 Exception。


Java 异常类层次结构图

1. Error

Error 是程序无法处理的错误,表示运行应用程序中较严重问题。大多数错误与代码编 写者执行的操作无关,而表示代码运行时 JVM(Java 虚拟机)出现的问题。例如,Java 虚拟机运行错误(Virtual MachineError),当 JVM 不再有继续执行操作所需的内存资源时,将出现 OutOfMemoryError。这些异常发生时,Java 虚拟机(JVM)一般会选择线 程终止。 Error 表明系统 JVM 已经处于不可恢复的崩溃状态中。我们不需要管他。


java.lang包下的Error类

2. Exception

Exception 是程序本身能够处理的异常,如:空指针异常(NullPointerException)、数 组 下 标 越 界 异 常 ( ArrayIndexOutOfBoundsException )、类 型 转 换 异 常 (ClassCastException)、算术异常(ArithmeticException)等。Exception 类是所有异常类的父类,其子类对应了各种各样可能出现的异常事件。
通常 Java 的异常可分为:

  1. RuntimeException 运行时异常
  2. CheckedException 已检查异常

3. RuntimeException

派生于 RuntimeException 的异常,如被 0 除、数组下标越界、空指针等,其产生比较频繁,处理麻烦,如果显式的声明或捕获将会对程序可读性和运行效率影响很大。 因此 由系统自动检测并将它们交给缺省的异常处理程序(用户可不必对其处理)。
这类异常通常是由编程错误导致的,所以在编写程序时,并不要求必须使用异常处理机 制来处理这类异常,经常需要通过增加“逻辑处理来避免这些异常”。
常见的运行时异常:

  1. ArithmeticException 异常:试图除以 0
public class Test3 { 
  public static void main(String[ ] args) { 
    int b=0; 
    System.out.println(1/b); 
  } 
}
image.png
  1. NullPointerException 异常
public class Test4 { 
  public static void main(String[ ] args) {
    String str=null; 
    System.out.println(str.charAt(0)); 
  } 
}
NullPointerException 异常
  1. ClassCastException 异常
class Animal{ 
}
class Dog extends Animal{
 }
class Cat extends Animal{ 
}
public class Test5 { 
  public static void main(String[ ] args) { 
    Animal a=new Dog(); 
    Cat c=(Cat)a; 
  } 
}
ClassCastException 异常
  1. ArrayIndexOutOfBoundsException 异常
public class Test6 { 
  public static void main(String[ ] args) {
    int[ ] arr = new int[5]; 
    System.out.println(arr[5]); 
  } 
}
ArrayIndexOutOfBoundsException 异常
  1. NumberFormatException 异常
public class Test7 { 
  public static void main(String[ ] args) {
    String str = "1234abcf"; 
    System.out.println(Integer.parseInt(str)); 
  } 
}
NumberFormatException 异常

4. CheckedException

所有不是 RuntimeException 的异常,统称为 Checked Exception,又被称为“已检 查异常”,如 IOException、SQLException 等以及用户自定义的 Exception 异常。 这类 异常在编译时就必须做出处理,否则无法通过编译。
异常的处理方式有两种:使用“try/catch”捕获异常、使用“throws” 声明异常。

二、异常捕获

捕获异常是通过 3 个关键词来实现的:try-catch-finally。用 try 来执行一段程序,如 果出现异常,系统抛出一个异常,可以通过它的类型来捕捉(catch)并处理它,最后一步 是通过 finally 语句为异常处理提供一个统一的出口,finally 所指定的代码都要被执行 (catch 语句可有多条;finally 语句最多只能有一条,根据自己的需要可有可无)。

try{
  可能出现异常的代码
}catch(异常类型 变量名){
  出现异常时执行的代码
}....catch(异常类型 变量名){
  出现异常时执行的代码
}finally{
  最后要执行的代码
}

注意:

  1. 一个try后可以有1~n个catch
  2. catch是从上到下依次判断执行,try中没有出现异常,不会执行catch判断捕获。一旦出现异常,try中后面的代码不会执行
  3. 如果catch中捕获的异常类型比较大,应放在最后
  4. finally:当前try ... catch的结构执行结束后,会执行finally中的代码(一般为释放资源的代码)
    例:
public class Test8 { 
  public static void main(String[ ] args) { 
    FileReader reader = null; 
    try {
      reader = new FileReader("d:/a.txt"); 
      char c = (char) reader.read(); 
      char c2 = (char) reader.read(); 
      System.out.println("" + c + c2); 
    } catch (FileNotFoundException e) { 
      e.printStackTrace(); 
    } catch (IOException e) { 
      e.printStackTrace(); 
    } finally {
      try {
         if (reader != null) { 
           reader.close(); 
         } 
      } catch (Exception e) {
           e.printStackTrace(); 
      } 
    } 
  } 
}

三、声明异常

当 CheckedException 产生时,不一定立刻处理它,可以再把异常 throws 出去。
在方法中使用 try-catch-finally 是由这个方法来处理异常。但是在一些情况下,当前方法并不需要处理发生的异常,而是向上传递给调用它的方法处理。
如果一个方法中可能产生某种异常,但是并不能确定如何处理这种异常,则应根据异常规范在方法的首部声明该方法可能抛出的异常。
如果一个方法抛出多个已检查异常,就必须在方法的首部列出所有的异常,之间以逗号隔开。

public static void readFile(String fileName) throws FileNotFoundException, IOException {
        FileReader in = new FileReader(fileName);
        int tem = 0;
        try {
            tem = in.read();
            while (tem != -1) {
                System.out.print((char) tem);
                tem = in.read();
            }
        } finally {
            if (in != null) {
                in.close();
            }
        }
    }

四、try-with-resource 自动关闭 Closable 接口的资源

public class Test8 {
    public static void main(String[] args) {
        try (FileReader reader = new FileReader("d:/a.txt");) { //try-with-resource
            char c = (char) reader.read();
            char c2 = (char) reader.read();
            System.out.println("" + c + c2);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

五、自定义异常

  • 在程序中,可能会遇到 JDK 提供的任何标准异常类都无法充分描述清楚我们想要 表达的问题,这种情况下可以创建自己的异常类,即自定义异常类。
  • 自定义异常类只需从 Exception 类或者它的子类派生一个子类即可。
  • 自定义异常类如果继承 Exception 类,则为受检查异常,必须对其进行处理;如果不想处理,可以让自定义异常类继承运行时异常 RuntimeException 类。
  • 习惯上,自定义异常类应该包含 2 个构造器:一个是默认的构造器,另一个是带 有详细信息的构造器。
class IllegalAgeException extends Exception {
    public IllegalAgeException() {
    }//带有详细信息的构造器,信息存储在 message 中 

    public IllegalAgeException(String message) {
        super(message);
    }
}

自定义异常的使用:

public void setAge(int age) throws IllegalAgeException { 
  if (age < 0) { 
    throw new IllegalAgeException("人的年龄不应该为负数"); 
  }
  this.age = age; 
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 什么是异常? 异常本质上是程序上的错误,错误在我们编写程序的过程中会经常发生,包括编译期间和运行期间的错误。 编译...
    若兮缘阅读 3,457评论 0 11
  • 目录介绍 1.什么是异常 2.异常2.1 异常的概述和分类【了解】2.2 JVM默认是如何处理异常的【理解】2.3...
    杨充211阅读 327评论 0 1
  • 2.JAVA异常 异常指不期而至的各种状况,如:文件找不到、网络连接失败、非法参数等。异常是一个事件,它发生在程...
    青城楼主阅读 571评论 0 0
  • 通俗编程——白话JAVA异常机制 - 代码之道,编程之法 - 博客频道 - CSDN.NEThttp://blog...
    葡萄喃喃呓语阅读 3,210评论 0 25
  • 概念介绍 异常是发生在程序执行过程中阻碍程序正常执行的错误事件,当一个程序出现错误时,可能的情况有如下3种: 语法...
    niaoge2016阅读 5,253评论 2 20