在 Java 中声明了很多异常类,每个异常类都表示一种运行错误。程序运行过程中发生一个可识别的运行错误时(可以找到与错误匹配的异常类,例如被除数为 0 时会触发 java.lang.ArithmeticException),系统会抛出对应异常类的对象。

参考:Java 异常处理

Java 异常处理机制的优点

  • 分离错误处理代码,使业务代码更专注
  • 按照类型对错误分组
  • 可以捕获处理无法预测的错误
  • 异常类的对象包含了异常的充分信息
  • 可以按照调用栈传播错误,直到有处理错误的代码

错误分类

根据错误的严重程度不同,可以分为两类:

  • 错误:致命的,无法处理的。最上层父类是 Error 类
  • 异常:非致命,可以捕获并处理。最上层父类是 Exception 类

Throwable 是 Error 和 Exception 的父类。

Java 中有3种方式生成异常对象:

  • 由 Java 虚拟机生成
  • 由 Java 类库中的某些类生成
  • 在自己写的程序中生成和抛出异常对象

必须通过 throw 语句抛异常对象,异常对象必须是 Throwable 或其子类的实例。

  1. throw new XXException();
  2. XXException e = new XXException();
  3. throw e;

Throwable 类的主要方法

方法 描述
public String getMessage() 获取异常的详细信息
public Throwable getCause() 返回 Throwable 对象,代表异常的原因
public void printStackTrace() 打印toString()结果和栈层次到 System.err 错误输出流。
public StackTraceElement [] getStackTrace() 返回一个包含堆栈层次的数组。下标为0的元素代表栈顶,最后一个元素代表方法调用堆栈的栈底。

异常的分类

根据是否必须捕获异常,可以将异常分为两类:

非检查型异常(也叫运行时异常)

非检查型异常继承自 RuntimeException,不需要在程序中进行捕获,编译器也不会检查。之所以可以不捕获,有两个原因:

  • 引发这类异常的操作经常出现(例如使用对象时如果对象为 null 则抛异常)
  • 要抛的异常可以用其他方式解决(例如被除数为0会抛出异常,但可以提前判断被除数来防止这种异常)
  1. public class Excep {
  2. public static void main(String[] args) {
  3. String[] arr = {"hello", "world"};
  4. int i = 0;
  5. while(i < 10) {
  6. System.out.println(arr[i++]);
  7. }
  8. }
  9. }

上面这段代码并没有捕获异常,编译通过,执行时会因为数组下标越界而报错:

  1. [root@VM_139_38_centos java]# java Excep
  2. hello
  3. world
  4. Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 2
  5. at Excep.main(Excep.java:6)

检查型异常

对于检查型异常,调用者必须捕获并处理(try{...}catch(...){...})或也声明抛出(`throws XXException``)。如果所有方法都没有处理这种异常,最终异常会交给 Java 虚拟机来处理。编译器会检查这种异常。

  1. public class T {
  2. public static void main(String[] args) {
  3. He h = new He();
  4. h.fun();
  5. }
  6. }
  7. class He {
  8. public void fun() throws Exception {
  9. throw new RuntimeException();
  10. }
  11. }

上面这段代码中,类 He 中的 fun 方法会抛出异常,当时调用者并没有捕获也没有继续抛出,所以执行时会报错:

  1. T.java:4: unreported exception java.lang.Exception; must be caught or declared to be thrown
  2. h.fun();
  3. ^
  4. 1 error

如果异常一路都在抛,没有方法处理,最后到了 main 方法还在抛异常public static void main(String[] args) throws Exception{...},那最后 Java 虚拟机会接收到这个异常,程序会停止执行并报错,例如:

  1. public class T {
  2. public static void main(String[] args) throws Exception{
  3. He h = new He();
  4. h.fun();
  5. System.out.println("end of program");
  6. }
  7. }
  8. class He {
  9. public void fun() throws Exception {
  10. throw new RuntimeException();
  11. }
  12. }
  1. [root@VM_139_38_centos java]# java T
  2. Exception in thread "main" java.lang.RuntimeException
  3. at He.fun(T.java:10)
  4. at T.main(T.java:4)

捕获并处理异常

Java 中用 try{...}catch(...){...}finally{...} 语句捕获异常。其中,try 代码段中是可能抛出异常的代码,catch 代码段在匹配异常时执行,finally 代码段则是无论是否发生异常都会执行的代码段。语法为:

  1. try {
  2. // 程序代码
  3. } catch(ExceptionName1 e1) {
  4. //Catch 块
  5. } catch(ExceptionName2 e2) {
  6. //可以有多个 Catch 块
  7. } finally {
  8. //finally 块
  9. }

例如,对于数组越界异常的捕获处理:

  1. public class ExcepTest{
  2. public static void main(String args[]){
  3. try{
  4. int a[] = new int[2];
  5. System.out.println("Access element three :" + a[3]);
  6. }catch(ArrayIndexOutOfBoundsException e){
  7. System.out.println("Exception thrown :" + e);
  8. }finally{
  9. System.out.println("finally run");
  10. }
  11. System.out.println("Out of the block");
  12. }
  13. }

结果为:

  1. Exception thrown :java.lang.ArrayIndexOutOfBoundsException: 3
  2. finally run
  3. Out of the block

throws/throw 关键字

对于检查性异常,如果方法不想捕获,那么该方法必须使用 throws 关键字来抛出这个异常(如果有多个可能的异常,需要用逗号分隔),交给调用者来处理。throws 关键字放在方法签名的尾部。

  1. public void fun() throws RemoteException, InsufficientFundsException
  2. {
  3. // Method implementation
  4. }

throw 关键字用于抛出异常给方法的调用者,注意需要在方法签名尾部用 throws 抛出这个异常。

  1. public void fun() throws RemoteException
  2. {
  3. throw new RemoteException();
  4. }

自定义异常

Java 中的异常类跟普通的类一样,有属性和方法。根据自定义的异常是否需要检查,可以分为两类:

  • 检查型异常类,需要继承 Exception 类。
  • 运行时异常类,需要继承 RuntimeException 类。

语法示例:

  1. class MyException extends Exception{
  2. }

代码示例:

  1. public class T {
  2. public static void main(String[] args) {
  3. try {
  4. throw new MyException(666);
  5. } catch (MyException e) {
  6. System.out.println(e);
  7. }
  8. }
  9. }
  10. class MyException extends Exception {
  11. private int amount;
  12. public MyException(int amount) {
  13. this.amount = amount;
  14. }
  15. public String getMessage() {
  16. return "amount not enough" + this.amount;
  17. }
  18. }

运行结果:

  1. MyException: amount not enough666

Java 基础-异常处理的更多相关文章

  1. Java基础—异常处理总结

      异常处理是程序设计中一个非常重要的方面,也是程序设计的一大难点,从C开始,你也许已经知道如何用if...else...来控制异常了,也许是自发的,然而这种控制异常痛苦,同一个异常或者错误如果多个地 ...

  2. 十二、Java基础---------异常处理机制

    异常 异常 异常就是程序在运行时产生的异常情况. 异常的由来 问题也是现实生活中的具体事物,也可以通过java 类的形式进行描述,并封装成对象.异常就是java 对不正常情况进行描述后的对象的体现. ...

  3. Java基础——异常处理

    异常的层次结构 所有的异常类都是 java.lang.Exception 类的子类型.异常类都是 Throwable 类的子类.除了异常类 Error 类也是由 Throwable 类产生的的子类1. ...

  4. Java基础--异常处理

    1.异常的传统处理方式 缺点: [1] 通过判断影响执行效率. [2] 判断逻辑和业务逻辑交织在一起,可维护性很差. public class Test01 { public static void ...

  5. java基础—异常处理

    一.异常的概念 异常指的是运行期出现的错误,也就是当程序开始执行以后执行期出现的错误.出现错误时观察错误的名字和行号最为重要.

  6. Java基础-异常处理机制 及异常处理的五个关键字:try/catch/finally/throw /throws

    笔记: /** 异常处理机制: 抓抛模型 * 1."抛", 一旦抛出,程序终止! printStackTrace()显示异常路径! * 2."抓", 抓住异常 ...

  7. java基础异常处理

    异常的定义:中断了正常指令流的事件. try..catch..finally结构: class Test{ public static void main(String[] args){ System ...

  8. Java基础(四)-异常处理机制及其设计

    本篇主要是记录自己所理解的Java异常处理机制(基于jdk1.7)以及怎么去处理和设计异常.还记得当初学习Java异常这块的时候都没怎么注意它的用途,以为就是简单的处理下异常,我避免程序出现这样错误就 ...

  9. Java基础学习之异常处理(6)

    @ 目录 1.异常是什么 1.1.Error 1.2.Exception 2.异常处理机制 2.1.捕获异常 2.2.抛出异常 3.自定义异常 3.1.自定义检查性异常 3.2.自定义运行时异常 1. ...

随机推荐

  1. PAT Advanced 1001 A+B Format (20 分)

    Calculate a+b and output the sum in standard format -- that is, the digits must be separated into gr ...

  2. 北京师范大学第十五届ACM决赛-重现赛K Keep In Line ( 字符串模拟实现)

    链接:https://ac.nowcoder.com/acm/contest/3/K 来源:牛客网 Keep In Line 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 26214 ...

  3. 面试经典&&竞赛——二叉树

    To record her trees for future generations, she wrote down two strings for each tree: a preorder tra ...

  4. STM32 JTAG接口SWD下载接线图

  5. Flutter SDK安装(windows)

    Flutter集成了Dart,因此不需要单独安装dart-sdk.Flutter的SDK可以从官网下载:https://flutter.io/sdk-archive/#windows 在Flutter ...

  6. python-抽象类和抽象方法

    需要模块  import abc 抽象类不能实例化 import abc class Animal(metaclass=abc.ABCMeta): #抽象类 @abc.abstractmethod # ...

  7. ipcloud上传裁切图片,保存为base64再压缩传给后台

    <!doctype html> <html> <head> <meta charset="utf-8"> <meta name ...

  8. linux使用shell 进行文件数据的读取与排序

    题目 shell脚本语言编写一个从键盘输入10名学生(含自己)的姓名. 性别.学号和家庭住址,然后按照学号排序,并将排序后的结果在屏幕上按对齐 的方式打印输出的程序. 代码 读入数据 数据排序(这里用 ...

  9. 嵌入QQ聊天

    <a href="http://wpa.qq.com/msgrd?V=1&Uin=1178321443&Site=http://www.nanfangjiadian.c ...

  10. 170907-关于JavaWeb的题

    1. 答案是B.D Servlet 通过调用 init () 方法进行初始化. Servlet 调用 service() 方法来处理客户端的请求. Servlet 通过调用 destroy() 方法终 ...